aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2019-11-10 06:17:09 -0500
committerJesse Luehrs <doy@tozt.net>2019-11-10 08:08:14 -0500
commit168a91a9ddc331cd3b8e5c32f7701f2b0973b147 (patch)
tree6b2df47bf18a731a9814bb875ce231e28cad1bf0 /src
parentb04c0e6e97765aeb888479c5e0bc27d54de60659 (diff)
downloadvt100-rust-168a91a9ddc331cd3b8e5c32f7701f2b0973b147.tar.gz
vt100-rust-168a91a9ddc331cd3b8e5c32f7701f2b0973b147.zip
optimize attribute setting a bit
Diffstat (limited to 'src')
-rw-r--r--src/attrs.rs6
-rw-r--r--src/cell.rs13
-rw-r--r--src/grid.rs21
-rw-r--r--src/row.rs28
-rw-r--r--src/screen.rs10
-rw-r--r--src/term.rs35
6 files changed, 86 insertions, 27 deletions
diff --git a/src/attrs.rs b/src/attrs.rs
index dc46646..4b78771 100644
--- a/src/attrs.rs
+++ b/src/attrs.rs
@@ -94,13 +94,13 @@ impl Attrs {
contents: &mut Vec<u8>,
other: &Self,
) {
- let attrs = crate::term::Attrs::default();
-
if self != other && self == &Self::default() {
- write!(contents, "{}", attrs).unwrap();
+ write!(contents, "{}", crate::term::ClearAttrs::new()).unwrap();
return;
}
+ let attrs = crate::term::Attrs::default();
+
let attrs = if self.fgcolor == other.fgcolor {
attrs
} else {
diff --git a/src/cell.rs b/src/cell.rs
index 61a3cd3..b9d7168 100644
--- a/src/cell.rs
+++ b/src/cell.rs
@@ -11,15 +11,22 @@ pub struct Cell {
attrs: crate::attrs::Attrs,
}
+#[allow(clippy::collapsible_if)]
impl PartialEq<Cell> for Cell {
fn eq(&self, other: &Self) -> bool {
- if self.attrs != other.attrs {
- return false;
- }
if self.len != other.len {
return false;
}
let len = self.len as usize;
+ if len > 0 {
+ if self.attrs != other.attrs {
+ return false;
+ }
+ } else {
+ if self.attrs.bgcolor != other.attrs.bgcolor {
+ return false;
+ }
+ }
self.contents[..len] == other.contents[..len]
}
}
diff --git a/src/grid.rs b/src/grid.rs
index 1cc4daf..a546c43 100644
--- a/src/grid.rs
+++ b/src/grid.rs
@@ -179,11 +179,14 @@ impl Grid {
}
}
- pub fn write_contents_formatted(&self, contents: &mut Vec<u8>) {
+ pub fn write_contents_formatted(
+ &self,
+ contents: &mut Vec<u8>,
+ ) -> crate::attrs::Attrs {
write!(
contents,
"{}{}",
- crate::term::Attrs::new(),
+ crate::term::ClearAttrs::new(),
crate::term::ClearScreen::new()
)
.unwrap();
@@ -211,13 +214,17 @@ impl Grid {
write!(contents, "{}", crate::term::MoveTo::new(self.pos))
.unwrap();
}
- }
- pub fn write_contents_diff(&self, contents: &mut Vec<u8>, prev: &Self) {
- write!(contents, "{}", crate::term::Attrs::default()).unwrap();
+ prev_attrs
+ }
+ pub fn write_contents_diff(
+ &self,
+ contents: &mut Vec<u8>,
+ prev: &Self,
+ mut prev_attrs: crate::attrs::Attrs,
+ ) -> crate::attrs::Attrs {
let mut prev_pos = prev.pos;
- let mut prev_attrs = crate::attrs::Attrs::default();
let mut wrapping = false;
for (i, (row, prev_row)) in
self.visible_rows().zip(prev.visible_rows()).enumerate()
@@ -242,6 +249,8 @@ impl Grid {
write!(contents, "{}", crate::term::MoveTo::new(self.pos))
.unwrap();
}
+
+ prev_attrs
}
pub fn erase_all(&mut self, bgcolor: crate::attrs::Color) {
diff --git a/src/row.rs b/src/row.rs
index f7d4485..1f10872 100644
--- a/src/row.rs
+++ b/src/row.rs
@@ -165,12 +165,13 @@ impl Row {
}
let attrs = cell.attrs();
- if &prev_attrs != attrs {
- attrs.write_escape_code_diff(contents, &prev_attrs);
- prev_attrs = *attrs;
- }
if has_contents {
+ if &prev_attrs != attrs {
+ attrs.write_escape_code_diff(contents, &prev_attrs);
+ prev_attrs = *attrs;
+ }
+
// using write! here is significantly slower, for some
// reason
// write!(contents, "{}", cell.contents()).unwrap();
@@ -179,6 +180,11 @@ impl Row {
prev_pos.col += width;
new_pos.col += width;
} else {
+ if prev_attrs.bgcolor != attrs.bgcolor {
+ attrs.write_escape_code_diff(contents, &prev_attrs);
+ prev_attrs = *attrs;
+ }
+
write!(
contents,
"{}",
@@ -262,12 +268,13 @@ impl Row {
}
let attrs = cell.attrs();
- if &prev_attrs != attrs {
- attrs.write_escape_code_diff(contents, &prev_attrs);
- prev_attrs = *attrs;
- }
if cell.has_contents() {
+ if &prev_attrs != attrs {
+ attrs.write_escape_code_diff(contents, &prev_attrs);
+ prev_attrs = *attrs;
+ }
+
// using write! here is significantly slower, for some
// reason
// write!(contents, "{}", cell.contents()).unwrap();
@@ -276,6 +283,11 @@ impl Row {
prev_pos.col += width;
new_pos.col += width;
} else {
+ if prev_attrs.bgcolor != attrs.bgcolor {
+ attrs.write_escape_code_diff(contents, &prev_attrs);
+ prev_attrs = *attrs;
+ }
+
write!(
contents,
"{}",
diff --git a/src/screen.rs b/src/screen.rs
index b774c10..c2fef6b 100644
--- a/src/screen.rs
+++ b/src/screen.rs
@@ -189,7 +189,8 @@ impl Screen {
crate::term::HideCursor::new(self.hide_cursor())
)
.unwrap();
- self.grid().write_contents_formatted(contents);
+ let prev_attrs = self.grid().write_contents_formatted(contents);
+ self.attrs.write_escape_code_diff(contents, &prev_attrs);
}
/// Returns the formatted contents of the terminal by row, restricted to
@@ -247,7 +248,12 @@ impl Screen {
)
.unwrap();
}
- self.grid().write_contents_diff(contents, prev.grid());
+ let prev_attrs = self.grid().write_contents_diff(
+ contents,
+ prev.grid(),
+ prev.attrs,
+ );
+ self.attrs.write_escape_code_diff(contents, &prev_attrs);
}
/// Returns a sequence of terminal byte streams sufficient to turn the
diff --git a/src/term.rs b/src/term.rs
index ef6c546..074f177 100644
--- a/src/term.rs
+++ b/src/term.rs
@@ -56,6 +56,21 @@ impl std::fmt::Display for MoveTo {
}
#[derive(Default, Debug)]
+pub struct ClearAttrs;
+
+impl ClearAttrs {
+ pub fn new() -> Self {
+ Self::default()
+ }
+}
+
+impl std::fmt::Display for ClearAttrs {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.write_str("\x1b[m")
+ }
+}
+
+#[derive(Default, Debug)]
pub struct Attrs {
fgcolor: Option<crate::attrs::Color>,
bgcolor: Option<crate::attrs::Color>,
@@ -66,10 +81,6 @@ pub struct Attrs {
}
impl Attrs {
- pub fn new() -> Self {
- Self::default()
- }
-
pub fn fgcolor(mut self, fgcolor: crate::attrs::Color) -> Self {
self.fgcolor = Some(fgcolor);
self
@@ -102,8 +113,22 @@ impl Attrs {
}
impl std::fmt::Display for Attrs {
- #[allow(unused_assignments, clippy::cognitive_complexity)]
+ #[allow(
+ unused_assignments,
+ clippy::cognitive_complexity,
+ clippy::too_many_lines
+ )]
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if self.fgcolor.is_none()
+ && self.bgcolor.is_none()
+ && self.bold.is_none()
+ && self.italic.is_none()
+ && self.underline.is_none()
+ && self.inverse.is_none()
+ {
+ return Ok(());
+ }
+
f.write_str("\x1b[")?;
let mut first = true;