mirror of
https://github.com/zellij-org/zellij.git
synced 2024-11-23 08:57:14 +03:00
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
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);
|
||||
}
|
||||
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,24 +1366,30 @@ impl Grid {
|
||||
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;
|
||||
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"))
|
||||
}
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user