aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2019-11-06 13:30:50 -0500
committerJesse Luehrs <doy@tozt.net>2019-11-06 13:30:50 -0500
commite21d3005c5ec2304f9f016cd506da93c78da5e51 (patch)
treea525767295c39544cc25926f15dde951abd59e8b
parentd778408be8b12fcc16a8fcaccde49bef927f22e0 (diff)
downloadvt100-rust-e21d3005c5ec2304f9f016cd506da93c78da5e51.tar.gz
vt100-rust-e21d3005c5ec2304f9f016cd506da93c78da5e51.zip
also add a rows_diff method
-rw-r--r--src/grid.rs2
-rw-r--r--src/row.rs11
-rw-r--r--src/screen.rs27
-rw-r--r--tests/window_contents.rs88
4 files changed, 109 insertions, 19 deletions
diff --git a/src/grid.rs b/src/grid.rs
index 075e604..fa6b4b9 100644
--- a/src/grid.rs
+++ b/src/grid.rs
@@ -177,7 +177,7 @@ impl Grid {
for (idx, (row, prev_row)) in self.rows().zip(prev.rows()).enumerate()
{
let (mut new_contents, new_attrs, new_col) =
- row.contents_diff(prev_row, prev_attrs);
+ row.contents_diff(prev_row, 0, self.size.cols, prev_attrs);
if !new_contents.is_empty() {
contents.extend(format!("\x1b[{};1H", idx + 1).as_bytes());
final_row = idx.try_into().unwrap();
diff --git a/src/row.rs b/src/row.rs
index fb31594..7b2ab99 100644
--- a/src/row.rs
+++ b/src/row.rs
@@ -126,14 +126,21 @@ impl Row {
pub fn contents_diff(
&self,
prev: &Self,
+ start: u16,
+ width: u16,
attrs: crate::attrs::Attrs,
) -> (Vec<u8>, crate::attrs::Attrs, u16) {
let mut skip = 0;
let mut contents = vec![];
let mut prev_attrs = attrs;
let mut final_col = 0;
- for (idx, (cell, prev_cell)) in
- self.cells().zip(prev.cells()).enumerate()
+
+ for (idx, (cell, prev_cell)) in self
+ .cells()
+ .zip(prev.cells())
+ .skip(start as usize)
+ .take(width as usize)
+ .enumerate()
{
if cell == prev_cell {
skip += 1;
diff --git a/src/screen.rs b/src/screen.rs
index 6aa80ba..873eeb3 100644
--- a/src/screen.rs
+++ b/src/screen.rs
@@ -211,6 +211,33 @@ impl Screen {
grid_contents
}
+ /// Returns a sequence of terminal byte streams sufficient to turn the
+ /// subset of each row from `prev` (as described by `start` and `width`)
+ /// into the corresponding row subset in `self`.
+ ///
+ /// You must handle the initial row positioning yourself - each row diff
+ /// expects to start out positioned at the start of that row. Internal
+ /// terminal modes (such as application keypad mode or alternate screen
+ /// mode) will not be included here.
+ pub fn rows_diff<'a>(
+ &'a self,
+ prev: &'a Self,
+ start: u16,
+ width: u16,
+ ) -> impl Iterator<Item = Vec<u8>> + 'a {
+ self.grid().rows().zip(prev.grid().rows()).map(
+ move |(row, prev_row)| {
+ let (contents, ..) = row.contents_diff(
+ prev_row,
+ start,
+ width,
+ crate::attrs::Attrs::default(),
+ );
+ contents
+ },
+ )
+ }
+
/// Returns the `Cell` object at the given location in the terminal, if it
/// exists.
pub fn cell(&self, row: u16, col: u16) -> Option<&crate::cell::Cell> {
diff --git a/tests/window_contents.rs b/tests/window_contents.rs
index 1d351cb..07a656d 100644
--- a/tests/window_contents.rs
+++ b/tests/window_contents.rs
@@ -72,8 +72,9 @@ fn empty_cells() {
#[test]
fn rows() {
let mut parser = vt100::Parser::new(24, 80);
+ let screen1 = parser.screen().clone();
assert_eq!(
- parser.screen().rows(0, 80).collect::<Vec<String>>(),
+ screen1.rows(0, 80).collect::<Vec<String>>(),
vec![
String::new(),
String::new(),
@@ -102,10 +103,7 @@ fn rows() {
]
);
assert_eq!(
- parser
- .screen()
- .rows_formatted(0, 80)
- .collect::<Vec<Vec<u8>>>(),
+ screen1.rows_formatted(0, 80).collect::<Vec<Vec<u8>>>(),
vec![
vec![],
vec![],
@@ -134,7 +132,7 @@ fn rows() {
]
);
assert_eq!(
- parser.screen().rows(5, 15).collect::<Vec<String>>(),
+ screen1.rows(5, 15).collect::<Vec<String>>(),
vec![
String::new(),
String::new(),
@@ -163,10 +161,7 @@ fn rows() {
]
);
assert_eq!(
- parser
- .screen()
- .rows_formatted(5, 15)
- .collect::<Vec<Vec<u8>>>(),
+ screen1.rows_formatted(5, 15).collect::<Vec<Vec<u8>>>(),
vec![
vec![],
vec![],
@@ -197,8 +192,9 @@ fn rows() {
parser
.process(b"\x1b[31mfoo\x1b[10;10H\x1b[32mbar\x1b[20;20H\x1b[33mbaz");
+ let screen2 = parser.screen().clone();
assert_eq!(
- parser.screen().rows(0, 80).collect::<Vec<String>>(),
+ screen2.rows(0, 80).collect::<Vec<String>>(),
vec![
"foo".to_string(),
String::new(),
@@ -227,8 +223,7 @@ fn rows() {
]
);
assert_eq!(
- parser
- .screen()
+ screen2
.rows_formatted(0, 80)
.collect::<Vec<Vec<u8>>>(),
vec![
@@ -259,7 +254,7 @@ fn rows() {
]
);
assert_eq!(
- parser.screen().rows(5, 15).collect::<Vec<String>>(),
+ screen2.rows(5, 15).collect::<Vec<String>>(),
vec![
String::new(),
String::new(),
@@ -288,8 +283,7 @@ fn rows() {
]
);
assert_eq!(
- parser
- .screen()
+ screen2
.rows_formatted(5, 15)
.collect::<Vec<Vec<u8>>>(),
vec![
@@ -319,6 +313,68 @@ fn rows() {
vec![],
]
);
+
+ assert_eq!(
+ screen2.rows_diff(&screen1, 0, 80).collect::<Vec<Vec<u8>>>(),
+ vec![
+ b"\x1b[31mfoo".to_vec(),
+ vec![],
+ vec![],
+ vec![],
+ vec![],
+ vec![],
+ vec![],
+ vec![],
+ vec![],
+ b"\x1b[9C\x1b[32mbar".to_vec(),
+ vec![],
+ vec![],
+ vec![],
+ vec![],
+ vec![],
+ vec![],
+ vec![],
+ vec![],
+ vec![],
+ b"\x1b[19C\x1b[33mbaz".to_vec(),
+ vec![],
+ vec![],
+ vec![],
+ vec![],
+ ]
+ );
+
+ parser.process(b"\x1b[10;11Ho");
+ let screen3 = parser.screen().clone();
+ assert_eq!(
+ screen3.rows_diff(&screen2, 0, 80).collect::<Vec<Vec<u8>>>(),
+ vec![
+ vec![],
+ vec![],
+ vec![],
+ vec![],
+ vec![],
+ vec![],
+ vec![],
+ vec![],
+ vec![],
+ b"\x1b[10C\x1b[33mo".to_vec(),
+ vec![],
+ vec![],
+ vec![],
+ vec![],
+ vec![],
+ vec![],
+ vec![],
+ vec![],
+ vec![],
+ vec![],
+ vec![],
+ vec![],
+ vec![],
+ vec![],
+ ]
+ );
}
#[test]