aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2019-11-12 15:37:31 -0500
committerJesse Luehrs <doy@tozt.net>2019-11-12 15:40:48 -0500
commite85e57949df612e22463c06fc31fb0b7957ea3c7 (patch)
tree02543dc13dd61c70be68a71a4f43aea4a5a9f30c
parent89654c576119ba958a57e9c557d974b657d7c986 (diff)
downloadvt100-rust-e85e57949df612e22463c06fc31fb0b7957ea3c7.tar.gz
vt100-rust-e85e57949df612e22463c06fc31fb0b7957ea3c7.zip
split formatted calculations into multiple methods
different applications want to be able to apply different things, so this gives more control
-rw-r--r--CHANGELOG.md16
-rw-r--r--src/screen.rs153
-rw-r--r--src/term.rs220
-rw-r--r--tests/control.rs13
-rw-r--r--tests/escape.rs23
-rw-r--r--tests/mode.rs228
-rw-r--r--tests/osc.rs77
7 files changed, 692 insertions, 38 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0971274..85eea08 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,21 @@
# Changelog
+## Unreleased
+
+### Added
+
+* `Screen::input_mode_formatted` and `Screen::input_mode_diff` give escape
+ codes to set the current terminal input modes.
+* `Screen::title_formatted` and `Screen::title_diff` give escape codes to set
+ the terminal window title.
+* `Screen::bells_diff` gives escape codes to trigger any audible or visual
+ bells which have been seen since the previous state.
+
+### Changed
+
+* `Screen::contents_diff` no longer includes audible or visual bells (see
+ `Screen::bells_diff` instead).
+
## [0.5.1] - 2019-11-12
### Fixed
diff --git a/src/screen.rs b/src/screen.rs
index d4613f0..3128f78 100644
--- a/src/screen.rs
+++ b/src/screen.rs
@@ -169,14 +169,11 @@ impl Screen {
})
}
- /// Returns the formatted contents of the terminal.
+ /// Returns the formatted visible contents of the terminal.
///
/// Formatting information will be included inline as terminal escape
/// codes. The result will be suitable for feeding directly to a raw
- /// terminal parser, and will result in the same visual output. Internal
- /// terminal modes (such as application keypad mode or alternate screen
- /// mode) will not be included here, but modes that affect the visible
- /// output (such as hidden cursor mode) will.
+ /// terminal parser, and will result in the same visual output.
pub fn contents_formatted(&self) -> Vec<u8> {
let mut contents = vec![];
self.write_contents_formatted(&mut contents);
@@ -189,16 +186,16 @@ impl Screen {
self.attrs.write_escape_code_diff(contents, &prev_attrs);
}
- /// Returns the formatted contents of the terminal by row, restricted to
- /// the given subset of columns.
+ /// Returns the formatted visible contents of the terminal by row,
+ /// restricted to the given subset of columns.
///
/// Formatting information will be included inline as terminal escape
/// codes. The result will be suitable for feeding directly to a raw
- /// terminal parser, and will result in the same visual output. Internal
- /// terminal modes (such as application keypad mode or alternate screen
- /// mode) will not be included here.
+ /// terminal parser, and will result in the same visual output.
///
- /// CRLF at the end of lines will not be included.
+ /// You are responsible for positioning the cursor before printing each
+ /// row, and final cursor position after displaying each row is
+ /// unspecified.
pub fn rows_formatted(
&self,
start: u16,
@@ -220,8 +217,9 @@ impl Screen {
})
}
- /// Returns a terminal byte stream sufficient to turn the screen described
- /// by `prev` into the screen described by `self`.
+ /// Returns a terminal byte stream sufficient to turn the visible contents
+ /// of the screen described by `prev` into the visible contents of the
+ /// screen described by `self`.
///
/// The result of rendering `prev.contents_formatted()` followed by
/// `self.contents_diff(prev)` should be equivalent to the result of
@@ -246,22 +244,16 @@ impl Screen {
prev.attrs,
);
self.attrs.write_escape_code_diff(contents, &prev_attrs);
- if self.audible_bell_count != prev.audible_bell_count {
- crate::term::AudibleBell::default().write_buf(contents);
- }
- if self.visual_bell_count != prev.visual_bell_count {
- crate::term::VisualBell::default().write_buf(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`.
+ /// visible contents of the subset of each row from `prev` (as described
+ /// by `start` and `width`) into the visible contents of 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.
+ /// You are responsible for positioning the cursor before printing each
+ /// row, and final cursor position after displaying each row is
+ /// unspecified.
pub fn rows_diff<'a>(
&'a self,
prev: &'a Self,
@@ -289,6 +281,117 @@ impl Screen {
})
}
+ pub fn input_mode_formatted(&self) -> Vec<u8> {
+ let mut contents = vec![];
+ self.write_input_mode_formatted(&mut contents);
+ contents
+ }
+
+ fn write_input_mode_formatted(&self, contents: &mut Vec<u8>) {
+ crate::term::ApplicationKeypad::new(
+ self.mode(Mode::ApplicationKeypad),
+ )
+ .write_buf(contents);
+ crate::term::ApplicationCursor::new(
+ self.mode(Mode::ApplicationCursor),
+ )
+ .write_buf(contents);
+ crate::term::BracketedPaste::new(self.mode(Mode::BracketedPaste))
+ .write_buf(contents);
+ crate::term::MouseProtocolMode::new(
+ self.mouse_protocol_mode,
+ MouseProtocolMode::None,
+ )
+ .write_buf(contents);
+ crate::term::MouseProtocolEncoding::new(
+ self.mouse_protocol_encoding,
+ MouseProtocolEncoding::Default,
+ )
+ .write_buf(contents);
+ }
+
+ pub fn input_mode_diff(&self, prev: &Self) -> Vec<u8> {
+ let mut contents = vec![];
+ self.write_input_mode_diff(&mut contents, prev);
+ contents
+ }
+
+ fn write_input_mode_diff(&self, contents: &mut Vec<u8>, prev: &Self) {
+ if self.mode(Mode::ApplicationKeypad)
+ != prev.mode(Mode::ApplicationKeypad)
+ {
+ crate::term::ApplicationKeypad::new(
+ self.mode(Mode::ApplicationKeypad),
+ )
+ .write_buf(contents);
+ }
+ if self.mode(Mode::ApplicationCursor)
+ != prev.mode(Mode::ApplicationCursor)
+ {
+ crate::term::ApplicationCursor::new(
+ self.mode(Mode::ApplicationCursor),
+ )
+ .write_buf(contents);
+ }
+ if self.mode(Mode::BracketedPaste) != prev.mode(Mode::BracketedPaste)
+ {
+ crate::term::BracketedPaste::new(self.mode(Mode::BracketedPaste))
+ .write_buf(contents);
+ }
+ crate::term::MouseProtocolMode::new(
+ self.mouse_protocol_mode,
+ prev.mouse_protocol_mode,
+ )
+ .write_buf(contents);
+ crate::term::MouseProtocolEncoding::new(
+ self.mouse_protocol_encoding,
+ prev.mouse_protocol_encoding,
+ )
+ .write_buf(contents);
+ }
+
+ pub fn title_formatted(&self) -> Vec<u8> {
+ let mut contents = vec![];
+ self.write_title_formatted(&mut contents);
+ contents
+ }
+
+ fn write_title_formatted(&self, contents: &mut Vec<u8>) {
+ crate::term::ChangeTitle::new(&self.icon_name, &self.title, "", "")
+ .write_buf(contents);
+ }
+
+ pub fn title_diff(&self, prev: &Self) -> Vec<u8> {
+ let mut contents = vec![];
+ self.write_title_diff(&mut contents, prev);
+ contents
+ }
+
+ fn write_title_diff(&self, contents: &mut Vec<u8>, prev: &Self) {
+ crate::term::ChangeTitle::new(
+ &self.icon_name,
+ &self.title,
+ &prev.icon_name,
+ &prev.title,
+ )
+ .write_buf(contents);
+ }
+
+ pub fn bells_diff(&self, prev: &Self) -> Vec<u8> {
+ let mut contents = vec![];
+ self.write_bells_diff(&mut contents, prev);
+ contents
+ }
+
+ fn write_bells_diff(&self, contents: &mut Vec<u8>, prev: &Self) {
+ if self.audible_bell_count != prev.audible_bell_count {
+ crate::term::AudibleBell::default().write_buf(contents);
+ }
+ if self.visual_bell_count != prev.visual_bell_count {
+ crate::term::VisualBell::default().write_buf(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/src/term.rs b/src/term.rs
index c988702..d2f7c9b 100644
--- a/src/term.rs
+++ b/src/term.rs
@@ -299,18 +299,18 @@ impl BufWrite for EraseChar {
#[derive(Default, Debug)]
#[must_use = "this struct does nothing unless you call write_buf"]
pub struct HideCursor {
- hide: bool,
+ state: bool,
}
impl HideCursor {
- pub fn new(hide: bool) -> Self {
- Self { hide }
+ pub fn new(state: bool) -> Self {
+ Self { state }
}
}
impl BufWrite for HideCursor {
fn write_buf(&self, buf: &mut Vec<u8>) {
- if self.hide {
+ if self.state {
buf.extend_from_slice(b"\x1b[?25l")
} else {
buf.extend_from_slice(b"\x1b[?25h")
@@ -364,3 +364,215 @@ impl BufWrite for VisualBell {
buf.extend_from_slice(b"\x1bg");
}
}
+
+#[must_use = "this struct does nothing unless you call write_buf"]
+pub struct ChangeTitle<'a> {
+ icon_name: &'a str,
+ title: &'a str,
+ prev_icon_name: &'a str,
+ prev_title: &'a str,
+}
+
+impl<'a> ChangeTitle<'a> {
+ pub fn new(
+ icon_name: &'a str,
+ title: &'a str,
+ prev_icon_name: &'a str,
+ prev_title: &'a str,
+ ) -> Self {
+ Self {
+ icon_name,
+ title,
+ prev_icon_name,
+ prev_title,
+ }
+ }
+}
+
+impl<'a> BufWrite for ChangeTitle<'a> {
+ fn write_buf(&self, buf: &mut Vec<u8>) {
+ if self.icon_name == self.title
+ && (self.icon_name != self.prev_icon_name
+ || self.title != self.prev_title)
+ {
+ buf.extend_from_slice(b"\x1b]0;");
+ buf.extend_from_slice(self.icon_name.as_bytes());
+ buf.push(b'\x07');
+ } else {
+ if self.icon_name != self.prev_icon_name {
+ buf.extend_from_slice(b"\x1b]1;");
+ buf.extend_from_slice(self.icon_name.as_bytes());
+ buf.push(b'\x07');
+ }
+ if self.title != self.prev_title {
+ buf.extend_from_slice(b"\x1b]2;");
+ buf.extend_from_slice(self.title.as_bytes());
+ buf.push(b'\x07');
+ }
+ }
+ }
+}
+
+#[derive(Default, Debug)]
+#[must_use = "this struct does nothing unless you call write_buf"]
+pub struct ApplicationKeypad {
+ state: bool,
+}
+
+impl ApplicationKeypad {
+ pub fn new(state: bool) -> Self {
+ Self { state }
+ }
+}
+
+impl BufWrite for ApplicationKeypad {
+ fn write_buf(&self, buf: &mut Vec<u8>) {
+ if self.state {
+ buf.extend_from_slice(b"\x1b=")
+ } else {
+ buf.extend_from_slice(b"\x1b>")
+ }
+ }
+}
+
+#[derive(Default, Debug)]
+#[must_use = "this struct does nothing unless you call write_buf"]
+pub struct ApplicationCursor {
+ state: bool,
+}
+
+impl ApplicationCursor {
+ pub fn new(state: bool) -> Self {
+ Self { state }
+ }
+}
+
+impl BufWrite for ApplicationCursor {
+ fn write_buf(&self, buf: &mut Vec<u8>) {
+ if self.state {
+ buf.extend_from_slice(b"\x1b[?1h")
+ } else {
+ buf.extend_from_slice(b"\x1b[?1l")
+ }
+ }
+}
+
+#[derive(Default, Debug)]
+#[must_use = "this struct does nothing unless you call write_buf"]
+pub struct BracketedPaste {
+ state: bool,
+}
+
+impl BracketedPaste {
+ pub fn new(state: bool) -> Self {
+ Self { state }
+ }
+}
+
+impl BufWrite for BracketedPaste {
+ fn write_buf(&self, buf: &mut Vec<u8>) {
+ if self.state {
+ buf.extend_from_slice(b"\x1b[?2004h")
+ } else {
+ buf.extend_from_slice(b"\x1b[?2004l")
+ }
+ }
+}
+
+#[derive(Default, Debug)]
+#[must_use = "this struct does nothing unless you call write_buf"]
+pub struct MouseProtocolMode {
+ mode: crate::screen::MouseProtocolMode,
+ prev: crate::screen::MouseProtocolMode,
+}
+
+impl MouseProtocolMode {
+ pub fn new(
+ mode: crate::screen::MouseProtocolMode,
+ prev: crate::screen::MouseProtocolMode,
+ ) -> Self {
+ Self { mode, prev }
+ }
+}
+
+impl BufWrite for MouseProtocolMode {
+ fn write_buf(&self, buf: &mut Vec<u8>) {
+ if self.mode == self.prev {
+ return;
+ }
+
+ match self.mode {
+ crate::screen::MouseProtocolMode::None => match self.prev {
+ crate::screen::MouseProtocolMode::None => {}
+ crate::screen::MouseProtocolMode::Press => {
+ buf.extend_from_slice(b"\x1b[?9l");
+ }
+ crate::screen::MouseProtocolMode::PressRelease => {
+ buf.extend_from_slice(b"\x1b[?1000l");
+ }
+ crate::screen::MouseProtocolMode::ButtonMotion => {
+ buf.extend_from_slice(b"\x1b[?1002l");
+ }
+ crate::screen::MouseProtocolMode::AnyMotion => {
+ buf.extend_from_slice(b"\x1b[?1003l");
+ }
+ },
+ crate::screen::MouseProtocolMode::Press => {
+ buf.extend_from_slice(b"\x1b[?9h");
+ }
+ crate::screen::MouseProtocolMode::PressRelease => {
+ buf.extend_from_slice(b"\x1b[?1000h");
+ }
+ crate::screen::MouseProtocolMode::ButtonMotion => {
+ buf.extend_from_slice(b"\x1b[?1002h");
+ }
+ crate::screen::MouseProtocolMode::AnyMotion => {
+ buf.extend_from_slice(b"\x1b[?1003h");
+ }
+ }
+ }
+}
+
+#[derive(Default, Debug)]
+#[must_use = "this struct does nothing unless you call write_buf"]
+pub struct MouseProtocolEncoding {
+ encoding: crate::screen::MouseProtocolEncoding,
+ prev: crate::screen::MouseProtocolEncoding,
+}
+
+impl MouseProtocolEncoding {
+ pub fn new(
+ encoding: crate::screen::MouseProtocolEncoding,
+ prev: crate::screen::MouseProtocolEncoding,
+ ) -> Self {
+ Self { encoding, prev }
+ }
+}
+
+impl BufWrite for MouseProtocolEncoding {
+ fn write_buf(&self, buf: &mut Vec<u8>) {
+ if self.encoding == self.prev {
+ return;
+ }
+
+ match self.encoding {
+ crate::screen::MouseProtocolEncoding::Default => {
+ match self.prev {
+ crate::screen::MouseProtocolEncoding::Default => {}
+ crate::screen::MouseProtocolEncoding::Utf8 => {
+ buf.extend_from_slice(b"\x1b[?1005l");
+ }
+ crate::screen::MouseProtocolEncoding::Sgr => {
+ buf.extend_from_slice(b"\x1b[?1006l");
+ }
+ }
+ }
+ crate::screen::MouseProtocolEncoding::Utf8 => {
+ buf.extend_from_slice(b"\x1b[?1005h");
+ }
+ crate::screen::MouseProtocolEncoding::Sgr => {
+ buf.extend_from_slice(b"\x1b[?1006h");
+ }
+ }
+ }
+}
diff --git a/tests/control.rs b/tests/control.rs
index 8372cea..e0dc276 100644
--- a/tests/control.rs
+++ b/tests/control.rs
@@ -9,27 +9,32 @@ fn bel() {
parser.process(b"\x07");
assert_eq!(parser.screen().audible_bell_count(), 1);
assert_eq!(parser.screen().audible_bell_count(), 1);
- assert_eq!(parser.screen().contents_diff(&screen), b"\x07");
+ assert_eq!(parser.screen().contents_diff(&screen), b"");
+ assert_eq!(parser.screen().bells_diff(&screen), b"\x07");
let screen = parser.screen().clone();
parser.process(b"\x07");
assert_eq!(parser.screen().audible_bell_count(), 2);
- assert_eq!(parser.screen().contents_diff(&screen), b"\x07");
+ assert_eq!(parser.screen().contents_diff(&screen), b"");
+ assert_eq!(parser.screen().bells_diff(&screen), b"\x07");
let screen = parser.screen().clone();
parser.process(b"\x07\x07\x07");
assert_eq!(parser.screen().audible_bell_count(), 5);
- assert_eq!(parser.screen().contents_diff(&screen), b"\x07");
+ assert_eq!(parser.screen().contents_diff(&screen), b"");
+ assert_eq!(parser.screen().bells_diff(&screen), b"\x07");
let screen = parser.screen().clone();
parser.process(b"foo");
assert_eq!(parser.screen().audible_bell_count(), 5);
assert_eq!(parser.screen().contents_diff(&screen), b"foo");
+ assert_eq!(parser.screen().bells_diff(&screen), b"");
let screen = parser.screen().clone();
parser.process(b"ba\x07r");
assert_eq!(parser.screen().audible_bell_count(), 6);
- assert_eq!(parser.screen().contents_diff(&screen), b"bar\x07");
+ assert_eq!(parser.screen().contents_diff(&screen), b"bar");
+ assert_eq!(parser.screen().bells_diff(&screen), b"\x07");
}
#[test]
diff --git a/tests/escape.rs b/tests/escape.rs
index 96ee762..67d6a87 100644
--- a/tests/escape.rs
+++ b/tests/escape.rs
@@ -68,6 +68,10 @@ fn ris() {
&b"\x1b[?25l\x1b[m\x1b[H\x1b[Jf\x1b[31;47;1;3;4moo\x1b[21;21H\x1b[7m"
[..]
);
+ assert_eq!(
+ parser.screen().title_formatted(),
+ &b"\x1b]1;window icon name\x07\x1b]2;window title\x07"[..]
+ );
assert_eq!(parser.screen().title(), "window title");
assert_eq!(parser.screen().icon_name(), "window icon name");
@@ -96,7 +100,11 @@ fn ris() {
assert_eq!(parser.screen().contents(), "");
assert_eq!(
parser.screen().contents_formatted(),
- b"\x1b[?25h\x1b[m\x1b[H\x1b[J"
+ &b"\x1b[?25h\x1b[m\x1b[H\x1b[J"[..]
+ );
+ assert_eq!(
+ parser.screen().title_formatted(),
+ &b"\x1b]1;window icon name\x07\x1b]2;window title\x07"[..]
);
// title and icon name don't change with reset
@@ -130,27 +138,32 @@ fn vb() {
parser.process(b"\x1bg");
assert_eq!(parser.screen().visual_bell_count(), 1);
assert_eq!(parser.screen().visual_bell_count(), 1);
- assert_eq!(parser.screen().contents_diff(&screen), b"\x1bg");
+ assert_eq!(parser.screen().contents_diff(&screen), b"");
+ assert_eq!(parser.screen().bells_diff(&screen), b"\x1bg");
let screen = parser.screen().clone();
parser.process(b"\x1bg");
assert_eq!(parser.screen().visual_bell_count(), 2);
- assert_eq!(parser.screen().contents_diff(&screen), b"\x1bg");
+ assert_eq!(parser.screen().contents_diff(&screen), b"");
+ assert_eq!(parser.screen().bells_diff(&screen), b"\x1bg");
let screen = parser.screen().clone();
parser.process(b"\x1bg\x1bg\x1bg");
assert_eq!(parser.screen().visual_bell_count(), 5);
- assert_eq!(parser.screen().contents_diff(&screen), b"\x1bg");
+ assert_eq!(parser.screen().contents_diff(&screen), b"");
+ assert_eq!(parser.screen().bells_diff(&screen), b"\x1bg");
let screen = parser.screen().clone();
parser.process(b"foo");
assert_eq!(parser.screen().visual_bell_count(), 5);
assert_eq!(parser.screen().contents_diff(&screen), b"foo");
+ assert_eq!(parser.screen().bells_diff(&screen), b"");
let screen = parser.screen().clone();
parser.process(b"ba\x1bgr");
assert_eq!(parser.screen().visual_bell_count(), 6);
- assert_eq!(parser.screen().contents_diff(&screen), b"bar\x1bg");
+ assert_eq!(parser.screen().contents_diff(&screen), b"bar");
+ assert_eq!(parser.screen().bells_diff(&screen), b"\x1bg");
}
#[test]
diff --git a/tests/mode.rs b/tests/mode.rs
index 5e222fe..e2404c6 100644
--- a/tests/mode.rs
+++ b/tests/mode.rs
@@ -15,7 +15,16 @@ fn modes() {
parser.screen().mouse_protocol_encoding(),
vt100::MouseProtocolEncoding::Default
);
+ assert_eq!(
+ parser.screen().contents_formatted(),
+ b"\x1b[?25h\x1b[m\x1b[H\x1b[J"
+ );
+ assert_eq!(
+ parser.screen().input_mode_formatted(),
+ b"\x1b>\x1b[?1l\x1b[?2004l"
+ );
+ let screen = parser.screen().clone();
parser.process(b"\x1b[?1h");
assert!(!parser.screen().application_keypad());
@@ -30,7 +39,18 @@ fn modes() {
parser.screen().mouse_protocol_encoding(),
vt100::MouseProtocolEncoding::Default
);
+ assert_eq!(
+ parser.screen().contents_formatted(),
+ b"\x1b[?25h\x1b[m\x1b[H\x1b[J"
+ );
+ assert_eq!(parser.screen().contents_diff(&screen), b"");
+ assert_eq!(
+ parser.screen().input_mode_formatted(),
+ b"\x1b>\x1b[?1h\x1b[?2004l"
+ );
+ assert_eq!(parser.screen().input_mode_diff(&screen), b"\x1b[?1h");
+ let screen = parser.screen().clone();
parser.process(b"\x1b[?9h");
assert!(!parser.screen().application_keypad());
@@ -45,7 +65,18 @@ fn modes() {
parser.screen().mouse_protocol_encoding(),
vt100::MouseProtocolEncoding::Default
);
+ assert_eq!(
+ parser.screen().contents_formatted(),
+ b"\x1b[?25h\x1b[m\x1b[H\x1b[J"
+ );
+ assert_eq!(parser.screen().contents_diff(&screen), b"");
+ assert_eq!(
+ parser.screen().input_mode_formatted(),
+ b"\x1b>\x1b[?1h\x1b[?2004l\x1b[?9h"
+ );
+ assert_eq!(parser.screen().input_mode_diff(&screen), b"\x1b[?9h");
+ let screen = parser.screen().clone();
parser.process(b"\x1b[?25l");
assert!(!parser.screen().application_keypad());
@@ -60,7 +91,18 @@ fn modes() {
parser.screen().mouse_protocol_encoding(),
vt100::MouseProtocolEncoding::Default
);
+ assert_eq!(
+ parser.screen().contents_formatted(),
+ b"\x1b[?25l\x1b[m\x1b[H\x1b[J"
+ );
+ assert_eq!(parser.screen().contents_diff(&screen), b"\x1b[?25l");
+ assert_eq!(
+ parser.screen().input_mode_formatted(),
+ b"\x1b>\x1b[?1h\x1b[?2004l\x1b[?9h"
+ );
+ assert_eq!(parser.screen().input_mode_diff(&screen), b"");
+ let screen = parser.screen().clone();
parser.process(b"\x1b[?1000h");
assert!(!parser.screen().application_keypad());
@@ -75,7 +117,18 @@ fn modes() {
parser.screen().mouse_protocol_encoding(),
vt100::MouseProtocolEncoding::Default
);
+ assert_eq!(
+ parser.screen().contents_formatted(),
+ b"\x1b[?25l\x1b[m\x1b[H\x1b[J"
+ );
+ assert_eq!(parser.screen().contents_diff(&screen), b"");
+ assert_eq!(
+ parser.screen().input_mode_formatted(),
+ b"\x1b>\x1b[?1h\x1b[?2004l\x1b[?1000h"
+ );
+ assert_eq!(parser.screen().input_mode_diff(&screen), b"\x1b[?1000h");
+ let screen = parser.screen().clone();
parser.process(b"\x1b[?1002h");
assert!(!parser.screen().application_keypad());
@@ -90,7 +143,18 @@ fn modes() {
parser.screen().mouse_protocol_encoding(),
vt100::MouseProtocolEncoding::Default
);
+ assert_eq!(
+ parser.screen().contents_formatted(),
+ b"\x1b[?25l\x1b[m\x1b[H\x1b[J"
+ );
+ assert_eq!(parser.screen().contents_diff(&screen), b"");
+ assert_eq!(
+ parser.screen().input_mode_formatted(),
+ b"\x1b>\x1b[?1h\x1b[?2004l\x1b[?1002h"
+ );
+ assert_eq!(parser.screen().input_mode_diff(&screen), b"\x1b[?1002h");
+ let screen = parser.screen().clone();
parser.process(b"\x1b[?1003h");
assert!(!parser.screen().application_keypad());
@@ -105,7 +169,18 @@ fn modes() {
parser.screen().mouse_protocol_encoding(),
vt100::MouseProtocolEncoding::Default
);
+ assert_eq!(
+ parser.screen().contents_formatted(),
+ b"\x1b[?25l\x1b[m\x1b[H\x1b[J"
+ );
+ assert_eq!(parser.screen().contents_diff(&screen), b"");
+ assert_eq!(
+ parser.screen().input_mode_formatted(),
+ b"\x1b>\x1b[?1h\x1b[?2004l\x1b[?1003h"
+ );
+ assert_eq!(parser.screen().input_mode_diff(&screen), b"\x1b[?1003h");
+ let screen = parser.screen().clone();
parser.process(b"\x1b[?1005h");
assert!(!parser.screen().application_keypad());
@@ -120,7 +195,18 @@ fn modes() {
parser.screen().mouse_protocol_encoding(),
vt100::MouseProtocolEncoding::Utf8
);
+ assert_eq!(
+ parser.screen().contents_formatted(),
+ b"\x1b[?25l\x1b[m\x1b[H\x1b[J"
+ );
+ assert_eq!(parser.screen().contents_diff(&screen), b"");
+ assert_eq!(
+ parser.screen().input_mode_formatted(),
+ b"\x1b>\x1b[?1h\x1b[?2004l\x1b[?1003h\x1b[?1005h"
+ );
+ assert_eq!(parser.screen().input_mode_diff(&screen), b"\x1b[?1005h");
+ let screen = parser.screen().clone();
parser.process(b"\x1b[?1006h");
assert!(!parser.screen().application_keypad());
@@ -135,7 +221,18 @@ fn modes() {
parser.screen().mouse_protocol_encoding(),
vt100::MouseProtocolEncoding::Sgr
);
+ assert_eq!(
+ parser.screen().contents_formatted(),
+ b"\x1b[?25l\x1b[m\x1b[H\x1b[J"
+ );
+ assert_eq!(parser.screen().contents_diff(&screen), b"");
+ assert_eq!(
+ parser.screen().input_mode_formatted(),
+ b"\x1b>\x1b[?1h\x1b[?2004l\x1b[?1003h\x1b[?1006h"
+ );
+ assert_eq!(parser.screen().input_mode_diff(&screen), b"\x1b[?1006h");
+ let screen = parser.screen().clone();
parser.process(b"\x1b[?2004h");
assert!(!parser.screen().application_keypad());
@@ -150,7 +247,18 @@ fn modes() {
parser.screen().mouse_protocol_encoding(),
vt100::MouseProtocolEncoding::Sgr
);
+ assert_eq!(
+ parser.screen().contents_formatted(),
+ b"\x1b[?25l\x1b[m\x1b[H\x1b[J"
+ );
+ assert_eq!(parser.screen().contents_diff(&screen), b"");
+ assert_eq!(
+ parser.screen().input_mode_formatted(),
+ b"\x1b>\x1b[?1h\x1b[?2004h\x1b[?1003h\x1b[?1006h"
+ );
+ assert_eq!(parser.screen().input_mode_diff(&screen), b"\x1b[?2004h");
+ let screen = parser.screen().clone();
parser.process(b"\x1b=");
assert!(parser.screen().application_keypad());
@@ -165,7 +273,18 @@ fn modes() {
parser.screen().mouse_protocol_encoding(),
vt100::MouseProtocolEncoding::Sgr
);
+ assert_eq!(
+ parser.screen().contents_formatted(),
+ b"\x1b[?25l\x1b[m\x1b[H\x1b[J"
+ );
+ assert_eq!(parser.screen().contents_diff(&screen), b"");
+ assert_eq!(
+ parser.screen().input_mode_formatted(),
+ b"\x1b=\x1b[?1h\x1b[?2004h\x1b[?1003h\x1b[?1006h"
+ );
+ assert_eq!(parser.screen().input_mode_diff(&screen), b"\x1b=");
+ let screen = parser.screen().clone();
parser.process(b"\x1b[?1l");
assert!(parser.screen().application_keypad());
@@ -180,7 +299,18 @@ fn modes() {
parser.screen().mouse_protocol_encoding(),
vt100::MouseProtocolEncoding::Sgr
);
+ assert_eq!(
+ parser.screen().contents_formatted(),
+ b"\x1b[?25l\x1b[m\x1b[H\x1b[J"
+ );
+ assert_eq!(parser.screen().contents_diff(&screen), b"");
+ assert_eq!(
+ parser.screen().input_mode_formatted(),
+ b"\x1b=\x1b[?1l\x1b[?2004h\x1b[?1003h\x1b[?1006h"
+ );
+ assert_eq!(parser.screen().input_mode_diff(&screen), b"\x1b[?1l");
+ let screen = parser.screen().clone();
parser.process(b"\x1b[?9l");
assert!(parser.screen().application_keypad());
@@ -195,7 +325,18 @@ fn modes() {
parser.screen().mouse_protocol_encoding(),
vt100::MouseProtocolEncoding::Sgr
);
+ assert_eq!(
+ parser.screen().contents_formatted(),
+ b"\x1b[?25l\x1b[m\x1b[H\x1b[J"
+ );
+ assert_eq!(parser.screen().contents_diff(&screen), b"");
+ assert_eq!(
+ parser.screen().input_mode_formatted(),
+ b"\x1b=\x1b[?1l\x1b[?2004h\x1b[?1003h\x1b[?1006h"
+ );
+ assert_eq!(parser.screen().input_mode_diff(&screen), b"");
+ let screen = parser.screen().clone();
parser.process(b"\x1b[?25h");
assert!(parser.screen().application_keypad());
@@ -210,7 +351,18 @@ fn modes() {
parser.screen().mouse_protocol_encoding(),
vt100::MouseProtocolEncoding::Sgr
);
+ assert_eq!(
+ parser.screen().contents_formatted(),
+ b"\x1b[?25h\x1b[m\x1b[H\x1b[J"
+ );
+ assert_eq!(parser.screen().contents_diff(&screen), b"\x1b[?25h");
+ assert_eq!(
+ parser.screen().input_mode_formatted(),
+ b"\x1b=\x1b[?1l\x1b[?2004h\x1b[?1003h\x1b[?1006h"
+ );
+ assert_eq!(parser.screen().input_mode_diff(&screen), b"");
+ let screen = parser.screen().clone();
parser.process(b"\x1b[?1000l");
assert!(parser.screen().application_keypad());
@@ -225,7 +377,18 @@ fn modes() {
parser.screen().mouse_protocol_encoding(),
vt100::MouseProtocolEncoding::Sgr
);
+ assert_eq!(
+ parser.screen().contents_formatted(),
+ b"\x1b[?25h\x1b[m\x1b[H\x1b[J"
+ );
+ assert_eq!(parser.screen().contents_diff(&screen), b"");
+ assert_eq!(
+ parser.screen().input_mode_formatted(),
+ b"\x1b=\x1b[?1l\x1b[?2004h\x1b[?1003h\x1b[?1006h"
+ );
+ assert_eq!(parser.screen().input_mode_diff(&screen), b"");
+ let screen = parser.screen().clone();
parser.process(b"\x1b[?1002l");
assert!(parser.screen().application_keypad());
@@ -240,7 +403,18 @@ fn modes() {
parser.screen().mouse_protocol_encoding(),
vt100::MouseProtocolEncoding::Sgr
);
+ assert_eq!(
+ parser.screen().contents_formatted(),
+ b"\x1b[?25h\x1b[m\x1b[H\x1b[J"
+ );
+ assert_eq!(parser.screen().contents_diff(&screen), b"");
+ assert_eq!(
+ parser.screen().input_mode_formatted(),
+ b"\x1b=\x1b[?1l\x1b[?2004h\x1b[?1003h\x1b[?1006h"
+ );
+ assert_eq!(parser.screen().input_mode_diff(&screen), b"");
+ let screen = parser.screen().clone();
parser.process(b"\x1b[?1003l");
assert!(parser.screen().application_keypad());
@@ -255,7 +429,18 @@ fn modes() {
parser.screen().mouse_protocol_encoding(),
vt100::MouseProtocolEncoding::Sgr
);
+ assert_eq!(
+ parser.screen().contents_formatted(),
+ b"\x1b[?25h\x1b[m\x1b[H\x1b[J"
+ );
+ assert_eq!(parser.screen().contents_diff(&screen), b"");
+ assert_eq!(
+ parser.screen().input_mode_formatted(),
+ b"\x1b=\x1b[?1l\x1b[?2004h\x1b[?1006h"
+ );
+ assert_eq!(parser.screen().input_mode_diff(&screen), b"\x1b[?1003l");
+ let screen = parser.screen().clone();
parser.process(b"\x1b[?1005l");
assert!(parser.screen().application_keypad());
@@ -270,7 +455,18 @@ fn modes() {
parser.screen().mouse_protocol_encoding(),
vt100::MouseProtocolEncoding::Sgr
);
+ assert_eq!(
+ parser.screen().contents_formatted(),
+ b"\x1b[?25h\x1b[m\x1b[H\x1b[J"
+ );
+ assert_eq!(parser.screen().contents_diff(&screen), b"");
+ assert_eq!(
+ parser.screen().input_mode_formatted(),
+ b"\x1b=\x1b[?1l\x1b[?2004h\x1b[?1006h"
+ );
+ assert_eq!(parser.screen().input_mode_diff(&screen), b"");
+ let screen = parser.screen().clone();
parser.process(b"\x1b[?1006l");
assert!(parser.screen().application_keypad());
@@ -285,7 +481,18 @@ fn modes() {
parser.screen().mouse_protocol_encoding(),
vt100::MouseProtocolEncoding::Default
);
+ assert_eq!(
+ parser.screen().contents_formatted(),
+ b"\x1b[?25h\x1b[m\x1b[H\x1b[J"
+ );
+ assert_eq!(parser.screen().contents_diff(&screen), b"");
+ assert_eq!(
+ parser.screen().input_mode_formatted(),
+ b"\x1b=\x1b[?1l\x1b[?2004h"
+ );
+ assert_eq!(parser.screen().input_mode_diff(&screen), b"\x1b[?1006l");
+ let screen = parser.screen().clone();
parser.process(b"\x1b[?2004l");
assert!(parser.screen().application_keypad());
@@ -300,7 +507,18 @@ fn modes() {
parser.screen().mouse_protocol_encoding(),
vt100::MouseProtocolEncoding::Default
);
+ assert_eq!(
+ parser.screen().contents_formatted(),
+ b"\x1b[?25h\x1b[m\x1b[H\x1b[J"
+ );
+ assert_eq!(parser.screen().contents_diff(&screen), b"");
+ assert_eq!(
+ parser.screen().input_mode_formatted(),
+ b"\x1b=\x1b[?1l\x1b[?2004l"
+ );
+ assert_eq!(parser.screen().input_mode_diff(&screen), b"\x1b[?2004l");
+ let screen = parser.screen().clone();
parser.process(b"\x1b>");
assert!(!parser.screen().application_keypad());
@@ -315,6 +533,16 @@ fn modes() {
parser.screen().mouse_protocol_encoding(),
vt100::MouseProtocolEncoding::Default
);
+ assert_eq!(
+ parser.screen().contents_formatted(),
+ b"\x1b[?25h\x1b[m\x1b[H\x1b[J"
+ );
+ assert_eq!(parser.screen().contents_diff(&screen), b"");
+ assert_eq!(
+ parser.screen().input_mode_formatted(),
+ b"\x1b>\x1b[?1l\x1b[?2004l"
+ );
+ assert_eq!(parser.screen().input_mode_diff(&screen), b"\x1b>");
}
#[test]
diff --git a/tests/osc.rs b/tests/osc.rs
index f9bcc67..7fd7e82 100644
--- a/tests/osc.rs
+++ b/tests/osc.rs
@@ -5,12 +5,26 @@ fn title() {
let mut parser = vt100::Parser::default();
assert_eq!(parser.screen().title(), "");
assert_eq!(parser.screen().icon_name(), "");
+
+ let screen = parser.screen().clone();
parser.process(b"\x1b]2;it's a title\x07");
assert_eq!(parser.screen().title(), "it's a title");
assert_eq!(parser.screen().icon_name(), "");
+ assert_eq!(
+ parser.screen().title_formatted(),
+ &b"\x1b]2;it's a title\x07"[..]
+ );
+ assert_eq!(
+ parser.screen().title_diff(&screen),
+ &b"\x1b]2;it's a title\x07"[..]
+ );
+
+ let screen = parser.screen().clone();
parser.process(b"\x1b]2;\x07");
assert_eq!(parser.screen().title(), "");
assert_eq!(parser.screen().icon_name(), "");
+ assert_eq!(parser.screen().title_formatted(), &b""[..]);
+ assert_eq!(parser.screen().title_diff(&screen), &b"\x1b]0;\x07"[..]);
}
#[test]
@@ -18,12 +32,26 @@ fn icon_name() {
let mut parser = vt100::Parser::default();
assert_eq!(parser.screen().title(), "");
assert_eq!(parser.screen().icon_name(), "");
+
+ let screen = parser.screen().clone();
parser.process(b"\x1b]1;it's an icon name\x07");
assert_eq!(parser.screen().title(), "");
assert_eq!(parser.screen().icon_name(), "it's an icon name");
+ assert_eq!(
+ parser.screen().title_formatted(),
+ &b"\x1b]1;it's an icon name\x07"[..]
+ );
+ assert_eq!(
+ parser.screen().title_diff(&screen),
+ &b"\x1b]1;it's an icon name\x07"[..]
+ );
+
+ let screen = parser.screen().clone();
parser.process(b"\x1b]1;\x07");
assert_eq!(parser.screen().title(), "");
assert_eq!(parser.screen().icon_name(), "");
+ assert_eq!(parser.screen().title_formatted(), &b""[..]);
+ assert_eq!(parser.screen().title_diff(&screen), &b"\x1b]0;\x07"[..]);
}
#[test]
@@ -31,12 +59,61 @@ fn title_icon_name() {
let mut parser = vt100::Parser::default();
assert_eq!(parser.screen().title(), "");
assert_eq!(parser.screen().icon_name(), "");
+
+ let screen = parser.screen().clone();
parser.process(b"\x1b]0;it's both\x07");
assert_eq!(parser.screen().title(), "it's both");
assert_eq!(parser.screen().icon_name(), "it's both");
+ assert_eq!(
+ parser.screen().title_formatted(),
+ &b"\x1b]0;it's both\x07"[..]
+ );
+ assert_eq!(
+ parser.screen().title_diff(&screen),
+ &b"\x1b]0;it's both\x07"[..]
+ );
+
+ let screen = parser.screen().clone();
parser.process(b"\x1b]0;\x07");
assert_eq!(parser.screen().title(), "");
assert_eq!(parser.screen().icon_name(), "");
+ assert_eq!(parser.screen().title_formatted(), &b""[..]);
+ assert_eq!(parser.screen().title_diff(&screen), &b"\x1b]0;\x07"[..]);
+
+ let screen = parser.screen().clone();
+ parser.process(b"\x1b]2;it's a title\x07\x1b]1;it's an icon name\x07");
+ assert_eq!(parser.screen().title(), "it's a title");
+ assert_eq!(parser.screen().icon_name(), "it's an icon name");
+ assert_eq!(
+ parser.screen().title_formatted(),
+ &b"\x1b]1;it's an icon name\x07\x1b]2;it's a title\x07"[..]
+ );
+ assert_eq!(
+ parser.screen().title_diff(&screen),
+ &b"\x1b]1;it's an icon name\x07\x1b]2;it's a title\x07"[..]
+ );
+
+ let screen = parser.screen().clone();
+ parser.process(b"\x1b]1;it's a title\x07");
+ assert_eq!(
+ parser.screen().title_formatted(),
+ &b"\x1b]0;it's a title\x07"[..]
+ );
+ assert_eq!(
+ parser.screen().title_diff(&screen),
+ &b"\x1b]0;it's a title\x07"[..]
+ );
+
+ let screen = parser.screen().clone();
+ parser.process(b"\x1b]1;it's an icon name\x07");
+ assert_eq!(
+ parser.screen().title_formatted(),
+ &b"\x1b]1;it's an icon name\x07\x1b]2;it's a title\x07"[..]
+ );
+ assert_eq!(
+ parser.screen().title_diff(&screen),
+ &b"\x1b]1;it's an icon name\x07"[..]
+ );
}
#[test]