aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2019-11-11 15:36:46 -0500
committerJesse Luehrs <doy@tozt.net>2019-11-11 15:49:00 -0500
commit30c8ad23f51a8bdc067e3a76da7004ba5be8682f (patch)
treef4c9d8da7468b53df99079b9ee14ea06943d7f2c
parent6203def48a689e30677a63b03d755aa0740e6e18 (diff)
downloadvt100-rust-30c8ad23f51a8bdc067e3a76da7004ba5be8682f.tar.gz
vt100-rust-30c8ad23f51a8bdc067e3a76da7004ba5be8682f.zip
optimize erases a bit more
-rw-r--r--src/row.rs126
-rw-r--r--src/term.rs15
-rw-r--r--tests/csi.rs34
-rw-r--r--tests/text.rs4
-rw-r--r--tests/window_contents.rs2
5 files changed, 119 insertions, 62 deletions
diff --git a/src/row.rs b/src/row.rs
index da5b398..52b6823 100644
--- a/src/row.rs
+++ b/src/row.rs
@@ -115,6 +115,7 @@ impl Row {
let mut prev_was_wide = false;
let default_cell = crate::cell::Cell::default();
+ let mut erase: Option<(u16, &crate::attrs::Attrs)> = None;
for (col, cell) in self
.cells()
.enumerate()
@@ -131,33 +132,61 @@ impl Row {
row,
col: col.try_into().unwrap(),
};
- if cell != &default_cell {
- if pos != prev_pos {
- if !wrapping
- || prev_pos.row + 1 != pos.row
- || prev_pos.col != self.cols()
- || pos.col != 0
- {
- crate::term::MoveFromTo::new(prev_pos, pos)
- .write_buf(contents);
+
+ if let Some((prev_col, attrs)) = erase {
+ if cell.has_contents() || cell.attrs() != attrs {
+ let new_pos = crate::grid::Pos { row, col: prev_col };
+ crate::term::MoveFromTo::new(prev_pos, new_pos)
+ .write_buf(contents);
+ prev_pos = new_pos;
+ if &prev_attrs != attrs {
+ attrs.write_escape_code_diff(contents, &prev_attrs);
+ prev_attrs = *attrs;
}
- prev_pos = pos;
+ crate::term::EraseChar::new(pos.col - prev_col)
+ .write_buf(contents);
+ erase = None;
}
+ }
+ if cell != &default_cell {
let attrs = cell.attrs();
- if &prev_attrs != attrs {
- attrs.write_escape_code_diff(contents, &prev_attrs);
- prev_attrs = *attrs;
- }
-
if cell.has_contents() {
+ if pos != prev_pos {
+ if !wrapping
+ || prev_pos.row + 1 != pos.row
+ || prev_pos.col != self.cols()
+ || pos.col != 0
+ {
+ crate::term::MoveFromTo::new(prev_pos, pos)
+ .write_buf(contents);
+ }
+ prev_pos = pos;
+ }
+
+ if &prev_attrs != attrs {
+ attrs.write_escape_code_diff(contents, &prev_attrs);
+ prev_attrs = *attrs;
+ }
+
contents.extend(cell.contents().as_bytes());
prev_pos.col += if cell.is_wide() { 2 } else { 1 };
- } else {
- crate::term::EraseChar::default().write_buf(contents);
+ } else if erase.is_none() {
+ erase = Some((pos.col, attrs));
}
}
}
+ if let Some((prev_col, attrs)) = erase {
+ let new_pos = crate::grid::Pos { row, col: prev_col };
+ crate::term::MoveFromTo::new(prev_pos, new_pos)
+ .write_buf(contents);
+ prev_pos = new_pos;
+ if &prev_attrs != attrs {
+ attrs.write_escape_code_diff(contents, &prev_attrs);
+ prev_attrs = *attrs;
+ }
+ crate::term::ClearRowForward::default().write_buf(contents);
+ }
(prev_pos, prev_attrs)
}
@@ -178,6 +207,7 @@ impl Row {
) -> (crate::grid::Pos, crate::attrs::Attrs) {
let mut prev_was_wide = false;
+ let mut erase: Option<(u16, &crate::attrs::Attrs)> = None;
for (col, (cell, prev_cell)) in self
.cells()
.zip(prev.cells())
@@ -195,33 +225,61 @@ impl Row {
row,
col: col.try_into().unwrap(),
};
- if cell != prev_cell {
- if pos != prev_pos {
- if !wrapping
- || prev_pos.row + 1 != pos.row
- || prev_pos.col != self.cols()
- || pos.col != 0
- {
- crate::term::MoveFromTo::new(prev_pos, pos)
- .write_buf(contents);
+
+ if let Some((prev_col, attrs)) = erase {
+ if cell.has_contents() || cell.attrs() != attrs {
+ let new_pos = crate::grid::Pos { row, col: prev_col };
+ crate::term::MoveFromTo::new(prev_pos, new_pos)
+ .write_buf(contents);
+ prev_pos = new_pos;
+ if &prev_attrs != attrs {
+ attrs.write_escape_code_diff(contents, &prev_attrs);
+ prev_attrs = *attrs;
}
- prev_pos = pos;
+ crate::term::EraseChar::new(pos.col - prev_col)
+ .write_buf(contents);
+ erase = None;
}
+ }
+ if cell != prev_cell {
let attrs = cell.attrs();
- if &prev_attrs != attrs {
- attrs.write_escape_code_diff(contents, &prev_attrs);
- prev_attrs = *attrs;
- }
-
if cell.has_contents() {
+ if pos != prev_pos {
+ if !wrapping
+ || prev_pos.row + 1 != pos.row
+ || prev_pos.col != self.cols()
+ || pos.col != 0
+ {
+ crate::term::MoveFromTo::new(prev_pos, pos)
+ .write_buf(contents);
+ }
+ prev_pos = pos;
+ }
+
+ if &prev_attrs != attrs {
+ attrs.write_escape_code_diff(contents, &prev_attrs);
+ prev_attrs = *attrs;
+ }
+
contents.extend(cell.contents().as_bytes());
prev_pos.col += if cell.is_wide() { 2 } else { 1 };
- } else {
- crate::term::EraseChar::default().write_buf(contents);
+ } else if erase.is_none() {
+ erase = Some((pos.col, attrs));
}
}
}
+ if let Some((prev_col, attrs)) = erase {
+ let new_pos = crate::grid::Pos { row, col: prev_col };
+ crate::term::MoveFromTo::new(prev_pos, new_pos)
+ .write_buf(contents);
+ prev_pos = new_pos;
+ if &prev_attrs != attrs {
+ attrs.write_escape_code_diff(contents, &prev_attrs);
+ prev_attrs = *attrs;
+ }
+ crate::term::ClearRowForward::default().write_buf(contents);
+ }
(prev_pos, prev_attrs)
}
diff --git a/src/term.rs b/src/term.rs
index 170e2ca..cb5488a 100644
--- a/src/term.rs
+++ b/src/term.rs
@@ -14,6 +14,15 @@ impl BufWrite for ClearScreen {
}
#[derive(Default, Debug)]
+pub struct ClearRowForward;
+
+impl BufWrite for ClearRowForward {
+ fn write_buf(&self, buf: &mut Vec<u8>) {
+ buf.extend_from_slice(b"\x1b[K");
+ }
+}
+
+#[derive(Default, Debug)]
pub struct CRLF;
impl BufWrite for CRLF {
@@ -253,6 +262,12 @@ pub struct EraseChar {
count: u16,
}
+impl EraseChar {
+ pub fn new(count: u16) -> Self {
+ Self { count }
+ }
+}
+
impl Default for EraseChar {
fn default() -> Self {
Self { count: 1 }
diff --git a/tests/csi.rs b/tests/csi.rs
index a57a578..1129ee1 100644
--- a/tests/csi.rs
+++ b/tests/csi.rs
@@ -209,10 +209,8 @@ fn ed() {
assert_eq!(
parser.screen().contents_formatted(),
format!(
- "\x1b[?25h\x1b[m\x1b[H\x1b[J\x1b[5;5H\x1b[41m{}\x1b[X\r\n{}{}\x1b[X\x1b[5;5H",
- "\x1b[X\x1b[C".repeat(75),
- format!("{}\x1b[X\r\n", "\x1b[X\x1b[C".repeat(79)).repeat(18),
- "\x1b[X\x1b[C".repeat(79),
+ "\x1b[?25h\x1b[m\x1b[H\x1b[J\x1b[5;5H\x1b[41m{}\x1b[K\x1b[5;5H",
+ "\x1b[K\r\n".repeat(19),
)
.as_bytes()
);
@@ -259,9 +257,8 @@ fn ed() {
assert_eq!(
parser.screen().contents_formatted(),
format!(
- "\x1b[?25h\x1b[m\x1b[H\x1b[J\x1b[41m{}{}\x1b[X",
- format!("{}\x1b[X\r\n", "\x1b[X\x1b[C".repeat(79)).repeat(4),
- "\x1b[X\x1b[C".repeat(4),
+ "\x1b[?25h\x1b[m\x1b[H\x1b[J\x1b[41m{}\x1b[5X\x1b[4C",
+ "\x1b[K\r\n".repeat(4),
)
.as_bytes()
);
@@ -308,9 +305,8 @@ fn ed() {
assert_eq!(
parser.screen().contents_formatted(),
format!(
- "\x1b[?25h\x1b[m\x1b[H\x1b[J\x1b[41m{}{}\x1b[5;5H",
- format!("{}\x1b[X\r\n", "\x1b[X\x1b[C".repeat(79)).repeat(23),
- format!("{}\x1b[X", "\x1b[X\x1b[C".repeat(79)),
+ "\x1b[?25h\x1b[m\x1b[H\x1b[J\x1b[41m{}\x1b[K\x1b[5;5H",
+ "\x1b[K\r\n".repeat(23),
)
.as_bytes()
);
@@ -421,11 +417,7 @@ fn el() {
);
assert_eq!(
parser.screen().contents_formatted(),
- format!(
- "\x1b[?25h\x1b[m\x1b[H\x1b[J\x1b[5;5H\x1b[41m{}\x1b[X\x1b[5;5H",
- "\x1b[X\x1b[C".repeat(75)
- )
- .as_bytes()
+ &b"\x1b[?25h\x1b[m\x1b[H\x1b[J\x1b[5;5H\x1b[41m\x1b[K"[..],
);
parser.process(b"\x1bc\x1b[5;5H");
@@ -461,11 +453,7 @@ fn el() {
);
assert_eq!(
parser.screen().contents_formatted(),
- format!(
- "\x1b[?25h\x1b[m\x1b[H\x1b[J\x1b[5;1H\x1b[41m{}\x1b[X",
- "\x1b[X\x1b[C".repeat(4),
- )
- .as_bytes()
+ &b"\x1b[?25h\x1b[m\x1b[H\x1b[J\x1b[5;1H\x1b[41m\x1b[5X\x1b[4C"[..],
);
parser.process(b"\x1bc\x1b[5;5H");
@@ -501,11 +489,7 @@ fn el() {
);
assert_eq!(
parser.screen().contents_formatted(),
- format!(
- "\x1b[?25h\x1b[m\x1b[H\x1b[J\x1b[5;1H\x1b[41m{}\x1b[X\x1b[5;5H",
- "\x1b[X\x1b[C".repeat(79),
- )
- .as_bytes()
+ &b"\x1b[?25h\x1b[m\x1b[H\x1b[J\x1b[5;1H\x1b[41m\x1b[K\x1b[4C"[..],
);
}
diff --git a/tests/text.rs b/tests/text.rs
index c49ded4..e0b4cee 100644
--- a/tests/text.rs
+++ b/tests/text.rs
@@ -100,7 +100,7 @@ fn wide() {
);
assert_eq!(
parser.screen().contents_diff(&screen),
- "\x1b[Hデcネfo\x1b[Cbar\x1b[X".as_bytes()
+ "\x1b[Hデcネfo\x1b[Cbar\x1b[K".as_bytes()
);
let screen = parser.screen().clone();
@@ -126,7 +126,7 @@ fn wide() {
);
assert_eq!(
parser.screen().contents_diff(&screen),
- "\x1b[Hデcネfo\x1b[Cbar\x1b[X".as_bytes()
+ "\x1b[Hデcネfo\x1b[Cbar\x1b[K".as_bytes()
);
}
diff --git a/tests/window_contents.rs b/tests/window_contents.rs
index 161402e..1bad9ed 100644
--- a/tests/window_contents.rs
+++ b/tests/window_contents.rs
@@ -106,7 +106,7 @@ fn cursor_positioning() {
parser.screen().contents_formatted(),
b"\x1b[?25h\x1b[m\x1b[H\x1b[J:"
);
- assert_eq!(parser.screen().contents_diff(&screen3), b"\x1b[1;2H\x1b[X");
+ assert_eq!(parser.screen().contents_diff(&screen3), b"\x1b[1;2H\x1b[K");
}
#[test]