From a3e69fe6da71638666522e42adb7aed6b5cfe52c Mon Sep 17 00:00:00 2001 From: Thomas Linford Date: Mon, 21 Feb 2022 17:58:54 +0100 Subject: [PATCH] fix(copy): rejoin wrapped lines (#1069) When copying wrapped lines do not treat them as separate lines. --- src/tests/fixtures/grid_copy_wrapped | 10 +++++++ zellij-server/src/panes/grid.rs | 34 +++++++++++++--------- zellij-server/src/panes/unit/grid_tests.rs | 24 +++++++++++++++ 3 files changed, 54 insertions(+), 14 deletions(-) create mode 100755 src/tests/fixtures/grid_copy_wrapped diff --git a/src/tests/fixtures/grid_copy_wrapped b/src/tests/fixtures/grid_copy_wrapped new file mode 100755 index 0000000000..f46d7dffe2 --- /dev/null +++ b/src/tests/fixtures/grid_copy_wrapped @@ -0,0 +1,10 @@ +Welcome to fish, the friendly interactive shell +Type `help` for instructions on how to use fish +[?2004h]0;fish /home/thomas/Projects/zellij(B  +zellij on  main [$!?] is 📦 v0.25.0 via 🦀 v1.58.1  +❯   c c (Bargo make run --debug (Bargo make run --debug (Bt(B cat (B lorem.txt (B lorem.txt (B lorem.txt (B  +(B[?2004l]0;cat lorem.txt /home/thomas/Projects/zellij(B Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. +⏎(B ⏎ [?2004h]0;fish /home/thomas/Projects/zellij(B +zellij on  main [$!?] is 📦 v0.25.0 via 🦀 v1.58.1  +❯   +(B(B[?2004l \ No newline at end of file diff --git a/zellij-server/src/panes/grid.rs b/zellij-server/src/panes/grid.rs index 11a77bfd95..b524c69b65 100644 --- a/zellij-server/src/panes/grid.rs +++ b/zellij-server/src/panes/grid.rs @@ -1291,27 +1291,27 @@ impl Grid { self.preceding_char = Some(terminal_character); } pub fn start_selection(&mut self, start: &Position) { - let old_selection = self.selection.clone(); + let old_selection = self.selection; self.selection.start(*start); self.update_selected_lines(&old_selection, &self.selection.clone()); self.mark_for_rerender(); } pub fn update_selection(&mut self, to: &Position) { - let old_selection = self.selection.clone(); + let old_selection = self.selection; self.selection.to(*to); self.update_selected_lines(&old_selection, &self.selection.clone()); self.mark_for_rerender(); } pub fn end_selection(&mut self, end: Option<&Position>) { - let old_selection = self.selection.clone(); + let old_selection = self.selection; self.selection.end(end); self.update_selected_lines(&old_selection, &self.selection.clone()); self.mark_for_rerender(); } pub fn reset_selection(&mut self) { - let old_selection = self.selection.clone(); + let old_selection = self.selection; self.selection.reset(); self.update_selected_lines(&old_selection, &self.selection.clone()); self.mark_for_rerender(); @@ -1366,25 +1366,31 @@ impl Grid { continue; }; - let excess_width = row.excess_width(); - let mut line: Vec = row.columns.iter().copied().collect(); - // pad line - line.resize( - self.width.saturating_sub(excess_width), - EMPTY_TERMINAL_CHARACTER, - ); - let mut terminal_col = 0; - for terminal_character in line { + for terminal_character in &row.columns { if (start_column..end_column).contains(&terminal_col) { line_selection.push(terminal_character.character); } terminal_col += terminal_character.width; } - selection.push(String::from(line_selection.trim_end())); + + if row.is_canonical { + selection.push(line_selection); + } else { + // rejoin wrapped lines if possible + match selection.last_mut() { + Some(previous_line) => previous_line.push_str(&line_selection), + None => selection.push(line_selection), + } + } } + // TODO: distinguish whitespace that was output explicitly vs implicitly (e.g add_newline) + // for example: echo " " vs empty lines + // for now trim after building the selection to handle whitespace in wrapped lines + let selection: Vec<_> = selection.iter().map(|l| l.trim_end()).collect(); + Some(selection.join("\n")) } diff --git a/zellij-server/src/panes/unit/grid_tests.rs b/zellij-server/src/panes/unit/grid_tests.rs index 9586352e06..72b1f55784 100644 --- a/zellij-server/src/panes/unit/grid_tests.rs +++ b/zellij-server/src/panes/unit/grid_tests.rs @@ -859,6 +859,30 @@ fn copy_selected_text_from_viewport() { ); } +#[test] +fn copy_wrapped_selected_text_from_viewport() { + let mut vte_parser = vte::Parser::new(); + let mut grid = Grid::new( + 22, + 73, + Palette::default(), + Rc::new(RefCell::new(LinkHandler::new())), + ); + let fixture_name = "grid_copy_wrapped"; + let content = read_fixture(fixture_name); + for byte in content { + vte_parser.advance(&mut grid, byte); + } + + grid.start_selection(&Position::new(5, 0)); + grid.end_selection(Some(&Position::new(8, 42))); + let text = grid.get_selected_text(); + assert_eq!( + text.unwrap(), + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." + ); +} + #[test] fn copy_selected_text_from_lines_above() { let mut vte_parser = vte::Parser::new();