aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2020-05-11 18:52:14 -0400
committerJesse Luehrs <doy@tozt.net>2020-05-11 18:52:14 -0400
commit0bc4834ae318502ac3575c0f7d073bbd3aedfe98 (patch)
tree0fc85599bb03731db91ab53eac7aef08135358d8
parent9cf895d45280bf8e89b1f05a6ff2fe34ab5a5e30 (diff)
downloadvt100-rust-0bc4834ae318502ac3575c0f7d073bbd3aedfe98.tar.gz
vt100-rust-0bc4834ae318502ac3575c0f7d073bbd3aedfe98.zip
add contents_between, for things like clipboard selections
-rw-r--r--src/screen.rs59
-rw-r--r--tests/window_contents.rs34
2 files changed, 93 insertions, 0 deletions
diff --git a/src/screen.rs b/src/screen.rs
index c50d077..a47bfa1 100644
--- a/src/screen.rs
+++ b/src/screen.rs
@@ -172,6 +172,65 @@ impl Screen {
})
}
+ /// Returns the text contents of the terminal logically between two cells.
+ /// This will include the remainder of the starting row after `start_col`,
+ /// followed by the entire contents of the rows between `start_row` and
+ /// `end_row`, followed by the beginning of the `end_row` up until
+ /// `end_col`. This is useful for things like determining the contents of
+ /// a clipboard selection.
+ #[must_use]
+ pub fn contents_between(
+ &self,
+ start_row: u16,
+ start_col: u16,
+ end_row: u16,
+ end_col: u16,
+ ) -> String {
+ match start_row.cmp(&end_row) {
+ std::cmp::Ordering::Less => {
+ let (_, cols) = self.size();
+ let mut contents = String::new();
+ for (i, row) in self
+ .grid()
+ .visible_rows()
+ .enumerate()
+ .skip(start_row as usize)
+ .take(end_row as usize - start_row as usize + 1)
+ {
+ if i == start_row as usize {
+ row.write_contents(
+ &mut contents,
+ start_col,
+ cols - start_col,
+ false,
+ );
+ if !row.wrapped() {
+ contents.push('\n');
+ }
+ } else if i == end_row as usize {
+ row.write_contents(&mut contents, 0, end_col, false);
+ } else {
+ row.write_contents(&mut contents, 0, cols, false);
+ if !row.wrapped() {
+ contents.push('\n');
+ }
+ }
+ }
+ contents
+ }
+ std::cmp::Ordering::Equal => {
+ if start_col < end_col {
+ self.rows(start_col, end_col - start_col)
+ .nth(start_row as usize)
+ .unwrap_or_else(String::new)
+ } else {
+ String::new()
+ }
+ }
+ std::cmp::Ordering::Greater => String::new(),
+ }
+ }
+
/// Returns the formatted visible contents of the terminal.
///
/// Formatting information will be included inline as terminal escape
diff --git a/tests/window_contents.rs b/tests/window_contents.rs
index 39c8ad7..a300438 100644
--- a/tests/window_contents.rs
+++ b/tests/window_contents.rs
@@ -453,6 +453,40 @@ fn rows() {
}
#[test]
+fn contents_between() {
+ let mut parser = vt100::Parser::default();
+ assert_eq!(parser.screen().contents_between(0, 0, 0, 0), "");
+ assert_eq!(parser.screen().contents_between(0, 0, 5, 0), "\n\n\n\n\n");
+ assert_eq!(parser.screen().contents_between(5, 0, 0, 0), "");
+
+ parser.process(
+ b"Lorem ipsum dolor sit amet, consectetur adipiscing elit, \
+ sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n\n\
+ Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris \
+ nisi ut aliquip ex ea commodo consequat.\n\n\
+ Duis aute irure dolor in reprehenderit in voluptate velit esse cillum \
+ dolore eu fugiat nulla pariatur.\n\n\
+ Excepteur sint occaecat cupidatat non proident, sunt in culpa qui \
+ officia deserunt mollit anim id est laborum.",
+ );
+ assert_eq!(parser.screen().contents_between(0, 0, 0, 0), "");
+ assert_eq!(
+ parser.screen().contents_between(0, 0, 0, 26),
+ "Lorem ipsum dolor sit amet"
+ );
+ assert_eq!(parser.screen().contents_between(0, 26, 0, 0), "");
+ assert_eq!(
+ parser.screen().contents_between(0, 57, 1, 43),
+ "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
+ );
+ assert_eq!(
+ parser.screen().contents_between(0, 57, 2, 0),
+ "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n"
+ );
+ assert_eq!(parser.screen().contents_between(2, 0, 0, 57), "");
+}
+
+#[test]
fn diff_basic() {
let mut parser = vt100::Parser::default();
let screen1 = parser.screen().clone();