editor: Fix duplicate and copy line newlines (#39610)

Closes #34797 and its child #39508.


![zed-#34797-#39508](https://github.com/user-attachments/assets/48a0fe28-8b8a-480d-bffc-6abc7ff310ff)

Release Notes:

- Fixed `editor::DuplicateLineUp` duplicating the last line onto itself
when the line doesn't end with a newline (#39508)
- Fixed line copy not including a newline at end of buffer, causing
paste to occur on the same line (#34797)
This commit is contained in:
Tom Planche
2025-10-08 22:56:25 +00:00
committed by GitHub
parent ba937d16e7
commit c1e3958c26
2 changed files with 93 additions and 6 deletions
+32 -6
View File
@@ -11687,13 +11687,26 @@ impl Editor {
rows.end.previous_row().0,
buffer.line_len(rows.end.previous_row()),
);
let text = buffer
.text_for_range(start..end)
.chain(Some("\n"))
.collect::<String>();
let mut text = buffer.text_for_range(start..end).collect::<String>();
let insert_location = if upwards {
Point::new(rows.end.0, 0)
// When duplicating upward, we need to insert before the current line.
// If we're on the last line and it doesn't end with a newline,
// we need to add a newline before the duplicated content.
let needs_leading_newline = rows.end.0 >= buffer.max_point().row
&& buffer.max_point().column > 0
&& !text.ends_with('\n');
if needs_leading_newline {
text.insert(0, '\n');
end
} else {
text.push('\n');
Point::new(rows.end.0, 0)
}
} else {
text.push('\n');
start
};
edits.push((insert_location..insert_location, text));
@@ -12503,9 +12516,18 @@ impl Editor {
let mut start = selection.start;
let mut end = selection.end;
let is_entire_line = selection.is_empty() || self.selections.line_mode();
let mut add_trailing_newline = false;
if is_entire_line {
start = Point::new(start.row, 0);
end = cmp::min(max_point, Point::new(end.row + 1, 0));
let next_line_start = Point::new(end.row + 1, 0);
if next_line_start <= max_point {
end = next_line_start;
} else {
// We're on the last line without a trailing newline.
// Copy to the end of the line and add a newline afterwards.
end = Point::new(end.row, buffer.line_len(MultiBufferRow(end.row)));
add_trailing_newline = true;
}
}
let mut trimmed_selections = Vec::new();
@@ -12556,6 +12578,10 @@ impl Editor {
text.push_str(chunk);
len += chunk.len();
}
if add_trailing_newline {
text.push('\n');
len += 1;
}
clipboard_selections.push(ClipboardSelection {
len,
is_entire_line,