Fix auto-indent when pasting multi-line content that was copied start… (#26246)

Closes https://github.com/zed-industries/zed/issues/24914 (again)

Release Notes:

- Fixed an issue where multi-line pasted content was auto-indented
incorrectly if copied from the middle of an existing line.
This commit is contained in:
Max Brunsfeld 2025-03-06 14:13:34 -08:00 committed by GitHub
parent f373383fc1
commit be75f17429
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 93 additions and 59 deletions

View file

@ -1012,8 +1012,8 @@ pub struct ClipboardSelection {
pub len: usize,
/// Whether this was a full-line selection.
pub is_entire_line: bool,
/// The column where this selection originally started.
pub start_column: u32,
/// The indentation of the first line when this content was originally copied.
pub first_line_indent: u32,
}
#[derive(Debug)]
@ -2354,7 +2354,7 @@ impl Editor {
pub fn edit_with_block_indent<I, S, T>(
&mut self,
edits: I,
original_start_columns: Vec<u32>,
original_indent_columns: Vec<Option<u32>>,
cx: &mut Context<Self>,
) where
I: IntoIterator<Item = (Range<S>, T)>,
@ -2369,7 +2369,7 @@ impl Editor {
buffer.edit(
edits,
Some(AutoindentMode::Block {
original_start_columns,
original_indent_columns,
}),
cx,
)
@ -3480,7 +3480,7 @@ impl Editor {
pub fn insert(&mut self, text: &str, window: &mut Window, cx: &mut Context<Self>) {
let autoindent = text.is_empty().not().then(|| AutoindentMode::Block {
original_start_columns: Vec::new(),
original_indent_columns: Vec::new(),
});
self.insert_with_autoindent_mode(text, autoindent, window, cx);
}
@ -8704,7 +8704,9 @@ impl Editor {
clipboard_selections.push(ClipboardSelection {
len,
is_entire_line,
start_column: selection.start.column,
first_line_indent: buffer
.indent_size_for_line(MultiBufferRow(selection.start.row))
.len,
});
}
}
@ -8783,7 +8785,7 @@ impl Editor {
clipboard_selections.push(ClipboardSelection {
len,
is_entire_line,
start_column: start.column,
first_line_indent: buffer.indent_size_for_line(MultiBufferRow(start.row)).len,
});
}
}
@ -8813,8 +8815,8 @@ impl Editor {
let old_selections = this.selections.all::<usize>(cx);
let all_selections_were_entire_line =
clipboard_selections.iter().all(|s| s.is_entire_line);
let first_selection_start_column =
clipboard_selections.first().map(|s| s.start_column);
let first_selection_indent_column =
clipboard_selections.first().map(|s| s.first_line_indent);
if clipboard_selections.len() != old_selections.len() {
clipboard_selections.drain(..);
}
@ -8829,21 +8831,21 @@ impl Editor {
let mut start_offset = 0;
let mut edits = Vec::new();
let mut original_start_columns = Vec::new();
let mut original_indent_columns = Vec::new();
for (ix, selection) in old_selections.iter().enumerate() {
let to_insert;
let entire_line;
let original_start_column;
let original_indent_column;
if let Some(clipboard_selection) = clipboard_selections.get(ix) {
let end_offset = start_offset + clipboard_selection.len;
to_insert = &clipboard_text[start_offset..end_offset];
entire_line = clipboard_selection.is_entire_line;
start_offset = end_offset + 1;
original_start_column = Some(clipboard_selection.start_column);
original_indent_column = Some(clipboard_selection.first_line_indent);
} else {
to_insert = clipboard_text.as_str();
entire_line = all_selections_were_entire_line;
original_start_column = first_selection_start_column
original_indent_column = first_selection_indent_column
}
// If the corresponding selection was empty when this slice of the
@ -8859,7 +8861,7 @@ impl Editor {
};
edits.push((range, to_insert));
original_start_columns.extend(original_start_column);
original_indent_columns.push(original_indent_column);
}
drop(snapshot);
@ -8867,7 +8869,7 @@ impl Editor {
edits,
if auto_indent_on_paste {
Some(AutoindentMode::Block {
original_start_columns,
original_indent_columns,
})
} else {
None