aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2019-11-12 05:47:32 -0500
committerJesse Luehrs <doy@tozt.net>2019-11-12 05:51:17 -0500
commit28eea9f6a837dad5febfe9b021b7070e96b286f9 (patch)
treec48d13955c045b892b95f6e652f8be22938705d1
parentbdda29c8e82e22bf49b5588f341549d3f94d6d30 (diff)
downloadvt100-rust-28eea9f6a837dad5febfe9b021b7070e96b286f9.tar.gz
vt100-rust-28eea9f6a837dad5febfe9b021b7070e96b286f9.zip
remove parser.screen_mut
it's easier to reason about if you are only able to get an immutable reference to the internal screen. this also required changing the api for bells.
-rw-r--r--CHANGELOG.md10
-rw-r--r--src/parser.rs26
-rw-r--r--src/screen.rs74
-rw-r--r--tests/basic.rs14
-rw-r--r--tests/control.rs11
-rw-r--r--tests/escape.rs24
-rw-r--r--tests/init.rs6
-rw-r--r--tests/scroll.rs20
8 files changed, 98 insertions, 87 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index bd0dc9f..c268b6c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,9 +8,19 @@
* `Default` impl for `Parser` which creates an 80x24 terminal with no
scrollback.
+### Removed
+
+* `Parser::screen_mut` (and the `pub` `&mut self` methods on `Screen`). The few
+ things you can do to change the screen state directly are now exposed as
+ methods on `Parser` itself.
+
### Changed
* `Cell::contents` now returns a `String` instead of a `&str`.
+* `Screen::check_audible_bell` and `Screen::check_visual_bell` have been
+ replaced with `Screen::audible_bell_count` and `Screen::visual_bell_count`.
+ You should keep track of the "since the last method call" state yourself
+ instead of having the screen track it for you.
### Fixed
diff --git a/src/parser.rs b/src/parser.rs
index 07ee7c9..613e18e 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -26,17 +26,31 @@ impl Parser {
}
}
+ /// Resizes the terminal.
+ pub fn set_size(&mut self, rows: u16, cols: u16) {
+ self.screen.set_size(rows, cols);
+ }
+
+ /// Scrolls to the given position in the scrollback.
+ ///
+ /// This position indicates the offset from the top of the screen, and
+ /// should be `0` to put the normal screen in view.
+ ///
+ /// This affects the return values of methods called on `parser.screen()`:
+ /// for instance, `parser.screen().cell(0, 0)` will return the top left
+ /// corner of the screen after taking the scrollback offset into account.
+ /// It does not affect `parser.process()` at all.
+ ///
+ /// The value given will be clamped to the actual size of the scrollback.
+ pub fn set_scrollback(&mut self, rows: usize) {
+ self.screen.set_scrollback(rows);
+ }
+
/// Returns a reference to a `Screen` object containing the terminal
/// state.
pub fn screen(&self) -> &crate::screen::Screen {
&self.screen
}
-
- /// Returns a mutable reference to a `Screen` object containing the
- /// terminal state.
- pub fn screen_mut(&mut self) -> &mut crate::screen::Screen {
- &mut self.screen
- }
}
impl Default for Parser {
diff --git a/src/screen.rs b/src/screen.rs
index 36a47c4..c2eaf0e 100644
--- a/src/screen.rs
+++ b/src/screen.rs
@@ -5,12 +5,6 @@ use unicode_width::UnicodeWidthChar as _;
const DEFAULT_MULTI_PARAMS: &[i64] = &[0];
#[derive(enumset::EnumSetType, Debug)]
-enum Output {
- AudibleBell,
- VisualBell,
-}
-
-#[derive(enumset::EnumSetType, Debug)]
enum Mode {
ApplicationKeypad,
ApplicationCursor,
@@ -84,10 +78,12 @@ pub struct Screen {
title: String,
icon_name: String,
- outputs: enumset::EnumSet<Output>,
modes: enumset::EnumSet<Mode>,
mouse_protocol_mode: MouseProtocolMode,
mouse_protocol_encoding: MouseProtocolEncoding,
+
+ audible_bell_count: usize,
+ visual_bell_count: usize,
}
impl Screen {
@@ -105,15 +101,16 @@ impl Screen {
title: String::default(),
icon_name: String::default(),
- outputs: enumset::EnumSet::default(),
modes: enumset::EnumSet::default(),
mouse_protocol_mode: MouseProtocolMode::default(),
mouse_protocol_encoding: MouseProtocolEncoding::default(),
+
+ audible_bell_count: 0,
+ visual_bell_count: 0,
}
}
- /// Resizes the terminal.
- pub fn set_size(&mut self, rows: u16, cols: u16) {
+ pub(crate) fn set_size(&mut self, rows: u16, cols: u16) {
self.grid.set_size(crate::grid::Size { rows, cols });
self.alternate_grid
.set_size(crate::grid::Size { rows, cols });
@@ -135,18 +132,7 @@ impl Screen {
self.grid().scrollback()
}
- /// Scrolls to the given position in the scrollback.
- ///
- /// This position indicates the offset from the top of the screen, and
- /// should be `0` to put the normal screen in view.
- ///
- /// This affects the return values of methods called on `parser.screen()`:
- /// for instance, `parser.screen().cell(0, 0)` will return the top left
- /// corner of the screen after taking the scrollback offset into account.
- /// It does not affect `parser.process()` at all.
- ///
- /// The value given will be clamped to the actual size of the scrollback.
- pub fn set_scrollback(&mut self, rows: usize) {
+ pub(crate) fn set_scrollback(&mut self, rows: usize) {
self.grid_mut().set_scrollback(rows);
}
@@ -321,16 +307,20 @@ impl Screen {
&self.icon_name
}
- /// Returns whether an audible bell has occurred since the last time this
- /// method was called.
- pub fn check_audible_bell(&mut self) -> bool {
- self.check_output(Output::AudibleBell)
+ /// Returns the total number of audible bells seen so far.
+ ///
+ /// Typically you would store this number after each call to `process`,
+ /// and trigger an audible bell whenever it changes.
+ pub fn audible_bell_count(&self) -> usize {
+ self.audible_bell_count
}
- /// Returns whether an visual bell has occurred since the last time this
- /// method was called.
- pub fn check_visual_bell(&mut self) -> bool {
- self.check_output(Output::VisualBell)
+ /// Returns the total number of visual bells seen so far.
+ ///
+ /// Typically you would store this number after each call to `process`,
+ /// and trigger an visual bell whenever it changes.
+ pub fn visual_bell_count(&self) -> usize {
+ self.visual_bell_count
}
/// Returns whether the terminal should be in application keypad mode.
@@ -413,20 +403,6 @@ impl Screen {
self.attrs = self.saved_attrs;
}
- fn set_output(&mut self, output: Output) {
- self.outputs.insert(output);
- }
-
- fn clear_output(&mut self, output: Output) {
- self.outputs.remove(output);
- }
-
- fn check_output(&mut self, output: Output) -> bool {
- let ret = self.outputs.contains(output);
- self.clear_output(output);
- ret
- }
-
fn set_mode(&mut self, mode: Mode) {
self.modes.insert(mode);
}
@@ -523,7 +499,7 @@ impl Screen {
// control codes
fn bel(&mut self) {
- self.set_output(Output::AudibleBell);
+ self.audible_bell_count += 1;
}
fn bs(&mut self) {
@@ -579,20 +555,22 @@ impl Screen {
// ESC c
fn ris(&mut self) {
- let outputs = self.outputs;
let title = self.title.clone();
let icon_name = self.icon_name.clone();
+ let audible_bell_count = self.audible_bell_count;
+ let visual_bell_count = self.visual_bell_count;
*self = Self::new(self.grid.size(), self.grid.scrollback_len());
- self.outputs = outputs;
self.title = title;
self.icon_name = icon_name;
+ self.audible_bell_count = audible_bell_count;
+ self.visual_bell_count = visual_bell_count;
}
// ESC g
fn vb(&mut self) {
- self.set_output(Output::VisualBell);
+ self.visual_bell_count += 1;
}
// csi codes
diff --git a/tests/basic.rs b/tests/basic.rs
index 0f2da75..33a272d 100644
--- a/tests/basic.rs
+++ b/tests/basic.rs
@@ -20,18 +20,18 @@ fn set_size() {
assert_eq!(parser.screen().size(), (24, 80));
assert_eq!(parser.screen().cursor_position(), (0, 0));
- parser.screen_mut().set_size(34, 8);
+ parser.set_size(34, 8);
assert_eq!(parser.screen().size(), (34, 8));
assert_eq!(parser.screen().cursor_position(), (0, 0));
parser.process(b"\x1b[30;5H");
assert_eq!(parser.screen().cursor_position(), (29, 4));
- parser.screen_mut().set_size(24, 80);
+ parser.set_size(24, 80);
assert_eq!(parser.screen().size(), (24, 80));
assert_eq!(parser.screen().cursor_position(), (23, 4));
- parser.screen_mut().set_size(34, 8);
+ parser.set_size(34, 8);
assert_eq!(parser.screen().size(), (34, 8));
assert_eq!(parser.screen().cursor_position(), (23, 4));
@@ -39,7 +39,7 @@ fn set_size() {
assert_eq!(parser.screen().size(), (34, 8));
assert_eq!(parser.screen().cursor_position(), (0, 0));
- parser.screen_mut().set_size(24, 80);
+ parser.set_size(24, 80);
assert_eq!(parser.screen().size(), (24, 80));
assert_eq!(parser.screen().cursor_position(), (0, 0));
@@ -47,14 +47,14 @@ fn set_size() {
assert_eq!(parser.screen().size(), (24, 80));
assert_eq!(parser.screen().cursor_position(), (23, 4));
- parser.screen_mut().set_size(34, 8);
+ parser.set_size(34, 8);
parser.process(b"\x1bc01234567890123456789");
assert_eq!(parser.screen().contents(), "01234567890123456789");
- parser.screen_mut().set_size(24, 80);
+ parser.set_size(24, 80);
assert_eq!(parser.screen().contents(), "01234567\n89012345\n6789");
- parser.screen_mut().set_size(34, 8);
+ parser.set_size(34, 8);
assert_eq!(parser.screen().contents(), "01234567\n89012345\n6789");
}
diff --git a/tests/control.rs b/tests/control.rs
index 9392b5e..aba6915 100644
--- a/tests/control.rs
+++ b/tests/control.rs
@@ -3,12 +3,17 @@
#[test]
fn bel() {
let mut parser = vt100::Parser::default();
+ assert_eq!(parser.screen().audible_bell_count(), 0);
- assert!(!parser.screen_mut().check_audible_bell());
+ parser.process(b"\x07");
+ assert_eq!(parser.screen().audible_bell_count(), 1);
+ assert_eq!(parser.screen().audible_bell_count(), 1);
parser.process(b"\x07");
- assert!(parser.screen_mut().check_audible_bell());
- assert!(!parser.screen_mut().check_audible_bell());
+ assert_eq!(parser.screen().audible_bell_count(), 2);
+
+ parser.process(b"\x07\x07\x07");
+ assert_eq!(parser.screen().audible_bell_count(), 5);
}
#[test]
diff --git a/tests/escape.rs b/tests/escape.rs
index 43eb666..e08a402 100644
--- a/tests/escape.rs
+++ b/tests/escape.rs
@@ -40,8 +40,8 @@ fn ris() {
assert_eq!(parser.screen().title(), "");
assert_eq!(parser.screen().icon_name(), "");
- assert!(!parser.screen_mut().check_visual_bell());
- assert!(!parser.screen_mut().check_audible_bell());
+ assert_eq!(parser.screen().audible_bell_count(), 0);
+ assert_eq!(parser.screen().visual_bell_count(), 0);
assert!(!parser.screen().application_keypad());
assert!(!parser.screen().application_cursor());
assert!(!parser.screen().hide_cursor());
@@ -72,8 +72,8 @@ fn ris() {
assert_eq!(parser.screen().title(), "window title");
assert_eq!(parser.screen().icon_name(), "window icon name");
- assert!(parser.screen_mut().check_visual_bell());
- assert!(parser.screen_mut().check_audible_bell());
+ assert_eq!(parser.screen().audible_bell_count(), 1);
+ assert_eq!(parser.screen().visual_bell_count(), 1);
assert!(parser.screen().application_keypad());
assert!(parser.screen().application_cursor());
assert!(parser.screen().hide_cursor());
@@ -87,7 +87,7 @@ fn ris() {
vt100::MouseProtocolEncoding::Sgr
);
- parser.process(b"\x07\x1bg\x1bc");
+ parser.process(b"\x1bc");
assert_eq!(parser.screen().cursor_position(), (0, 0));
let cell = parser.screen().cell(0, 0).unwrap();
@@ -104,8 +104,8 @@ fn ris() {
assert_eq!(parser.screen().icon_name(), "window icon name");
// bell states don't change with reset
- assert!(parser.screen_mut().check_visual_bell());
- assert!(parser.screen_mut().check_audible_bell());
+ assert_eq!(parser.screen().audible_bell_count(), 1);
+ assert_eq!(parser.screen().visual_bell_count(), 1);
assert!(!parser.screen().application_keypad());
assert!(!parser.screen().application_cursor());
@@ -124,10 +124,14 @@ fn ris() {
#[test]
fn vb() {
let mut parser = vt100::Parser::default();
- assert!(!parser.screen_mut().check_visual_bell());
+ assert_eq!(parser.screen().visual_bell_count(), 0);
parser.process(b"\x1bg");
- assert!(parser.screen_mut().check_visual_bell());
- assert!(!parser.screen_mut().check_visual_bell());
+ assert_eq!(parser.screen().visual_bell_count(), 1);
+ assert_eq!(parser.screen().visual_bell_count(), 1);
+ parser.process(b"\x1bg");
+ assert_eq!(parser.screen().visual_bell_count(), 2);
+ parser.process(b"\x1bg\x1bg\x1bg");
+ assert_eq!(parser.screen().visual_bell_count(), 5);
}
#[test]
diff --git a/tests/init.rs b/tests/init.rs
index ccb1c70..4e0cd66 100644
--- a/tests/init.rs
+++ b/tests/init.rs
@@ -2,7 +2,7 @@
#[test]
fn init() {
- let mut parser = vt100::Parser::default();
+ let parser = vt100::Parser::default();
assert_eq!(parser.screen().size(), (24, 80));
assert_eq!(parser.screen().cursor_position(), (0, 0));
@@ -24,8 +24,8 @@ fn init() {
assert_eq!(parser.screen().title(), "");
assert_eq!(parser.screen().icon_name(), "");
- assert!(!parser.screen_mut().check_visual_bell());
- assert!(!parser.screen_mut().check_audible_bell());
+ assert_eq!(parser.screen().audible_bell_count(), 0);
+ assert_eq!(parser.screen().visual_bell_count(), 0);
assert!(!parser.screen().application_keypad());
assert!(!parser.screen().application_cursor());
assert!(!parser.screen().hide_cursor());
diff --git a/tests/scroll.rs b/tests/scroll.rs
index 32b7488..2b1117e 100644
--- a/tests/scroll.rs
+++ b/tests/scroll.rs
@@ -82,31 +82,31 @@ fn scrollback() {
parser.process(b"\r\n25\r\n26\r\n27\r\n28\r\n29\r\n30");
assert_eq!(parser.screen().contents(), "7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n30");
- parser.screen_mut().set_scrollback(0);
+ parser.set_scrollback(0);
assert_eq!(parser.screen().scrollback(), 0);
assert_eq!(parser.screen().contents(), "7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n30");
- parser.screen_mut().set_scrollback(1);
+ parser.set_scrollback(1);
assert_eq!(parser.screen().scrollback(), 1);
assert_eq!(parser.screen().contents(), "6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29");
- parser.screen_mut().set_scrollback(3);
+ parser.set_scrollback(3);
assert_eq!(parser.screen().scrollback(), 3);
assert_eq!(parser.screen().contents(), "4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27");
- parser.screen_mut().set_scrollback(6);
+ parser.set_scrollback(6);
assert_eq!(parser.screen().scrollback(), 6);
assert_eq!(parser.screen().contents(), "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24");
- parser.screen_mut().set_scrollback(7);
+ parser.set_scrollback(7);
assert_eq!(parser.screen().scrollback(), 6);
assert_eq!(parser.screen().contents(), "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24");
- parser.screen_mut().set_scrollback(0);
+ parser.set_scrollback(0);
assert_eq!(parser.screen().scrollback(), 0);
assert_eq!(parser.screen().contents(), "7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n30");
- parser.screen_mut().set_scrollback(7);
+ parser.set_scrollback(7);
assert_eq!(parser.screen().scrollback(), 6);
assert_eq!(parser.screen().contents(), "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24");
@@ -134,11 +134,11 @@ fn scrollback() {
assert_eq!(parser.screen().scrollback(), 10);
assert_eq!(parser.screen().contents(), "3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26");
- parser.screen_mut().set_scrollback(12);
+ parser.set_scrollback(12);
assert_eq!(parser.screen().scrollback(), 10);
assert_eq!(parser.screen().contents(), "3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26");
- parser.screen_mut().set_scrollback(0);
+ parser.set_scrollback(0);
assert_eq!(parser.screen().scrollback(), 0);
assert_eq!(parser.screen().contents(), "13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n30\n31\n32\n33\n34\n35\n36");
@@ -146,7 +146,7 @@ fn scrollback() {
assert_eq!(parser.screen().scrollback(), 0);
assert_eq!(parser.screen().contents(), "15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n30\n31\n32\n33\n34\n35\n36\n37\n38");
- parser.screen_mut().set_scrollback(5);
+ parser.set_scrollback(5);
assert_eq!(parser.screen().scrollback(), 5);
assert_eq!(parser.screen().contents(), "10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n30\n31\n32\n33");