fix(copy): rejoin wrapped lines (#1069)
When copying wrapped lines do not treat them as separate lines.
This commit is contained in:
parent
0ac524b295
commit
a3e69fe6da
3 changed files with 54 additions and 14 deletions
10
src/tests/fixtures/grid_copy_wrapped
vendored
Executable file
10
src/tests/fixtures/grid_copy_wrapped
vendored
Executable file
|
|
@ -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[30m(B[m
[K[J[K
|
||||||
|
[1;36mzellij[0m on [1;35m main[0m [1;31m[$!?][0m is [1;38;5;208m📦 v0.25.0[0m via [1;31m🦀 v1.58.1 [0m
|
||||||
|
[1;32m❯[0m [K
[C[C
[C[Cc[J
[3C[38;2;255;0;0mc
[3C[30m(B[m[38;2;85;85;85margo make run --debug
[3C[30m(B[m[38;2;255;0;0ma[38;2;85;85;85mrgo make run --debug
[4C[30m(B[m[38;2;255;0;0mt[30m(B[m[K
[5C[38;2;0;95;215mcat
[5C[30m(B[m[38;2;85;85;85m lorem.txt
[5C[30m(B[m[38;2;0;95;215m lorem.txt
[15C[30m(B[m[10D [38;2;0;175;255m[4mlorem.txt
[15C[30m(B[m
[15C
|
||||||
|
[30m(B[m[?2004l]0;cat lorem.txt /home/thomas/Projects/zellij[30m(B[m
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||||
|
[2m⏎(B[m
⏎
[K[?2004h]0;fish /home/thomas/Projects/zellij[30m(B[m[K[J[K
|
||||||
|
[1;36mzellij[0m on [1;35m main[0m [1;31m[$!?][0m is [1;38;5;208m📦 v0.25.0[0m via [1;31m🦀 v1.58.1 [0m
|
||||||
|
[1;32m❯[0m [K
[C[C
|
||||||
|
[30m(B[m[30m(B[m[?2004l
|
||||||
|
|
@ -1291,27 +1291,27 @@ impl Grid {
|
||||||
self.preceding_char = Some(terminal_character);
|
self.preceding_char = Some(terminal_character);
|
||||||
}
|
}
|
||||||
pub fn start_selection(&mut self, start: &Position) {
|
pub fn start_selection(&mut self, start: &Position) {
|
||||||
let old_selection = self.selection.clone();
|
let old_selection = self.selection;
|
||||||
self.selection.start(*start);
|
self.selection.start(*start);
|
||||||
self.update_selected_lines(&old_selection, &self.selection.clone());
|
self.update_selected_lines(&old_selection, &self.selection.clone());
|
||||||
self.mark_for_rerender();
|
self.mark_for_rerender();
|
||||||
}
|
}
|
||||||
pub fn update_selection(&mut self, to: &Position) {
|
pub fn update_selection(&mut self, to: &Position) {
|
||||||
let old_selection = self.selection.clone();
|
let old_selection = self.selection;
|
||||||
self.selection.to(*to);
|
self.selection.to(*to);
|
||||||
self.update_selected_lines(&old_selection, &self.selection.clone());
|
self.update_selected_lines(&old_selection, &self.selection.clone());
|
||||||
self.mark_for_rerender();
|
self.mark_for_rerender();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn end_selection(&mut self, end: Option<&Position>) {
|
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.selection.end(end);
|
||||||
self.update_selected_lines(&old_selection, &self.selection.clone());
|
self.update_selected_lines(&old_selection, &self.selection.clone());
|
||||||
self.mark_for_rerender();
|
self.mark_for_rerender();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset_selection(&mut self) {
|
pub fn reset_selection(&mut self) {
|
||||||
let old_selection = self.selection.clone();
|
let old_selection = self.selection;
|
||||||
self.selection.reset();
|
self.selection.reset();
|
||||||
self.update_selected_lines(&old_selection, &self.selection.clone());
|
self.update_selected_lines(&old_selection, &self.selection.clone());
|
||||||
self.mark_for_rerender();
|
self.mark_for_rerender();
|
||||||
|
|
@ -1366,24 +1366,30 @@ impl Grid {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
let excess_width = row.excess_width();
|
|
||||||
let mut line: Vec<TerminalCharacter> = row.columns.iter().copied().collect();
|
|
||||||
// pad line
|
|
||||||
line.resize(
|
|
||||||
self.width.saturating_sub(excess_width),
|
|
||||||
EMPTY_TERMINAL_CHARACTER,
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut terminal_col = 0;
|
let mut terminal_col = 0;
|
||||||
for terminal_character in line {
|
for terminal_character in &row.columns {
|
||||||
if (start_column..end_column).contains(&terminal_col) {
|
if (start_column..end_column).contains(&terminal_col) {
|
||||||
line_selection.push(terminal_character.character);
|
line_selection.push(terminal_character.character);
|
||||||
}
|
}
|
||||||
|
|
||||||
terminal_col += terminal_character.width;
|
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"))
|
Some(selection.join("\n"))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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]
|
#[test]
|
||||||
fn copy_selected_text_from_lines_above() {
|
fn copy_selected_text_from_lines_above() {
|
||||||
let mut vte_parser = vte::Parser::new();
|
let mut vte_parser = vte::Parser::new();
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue