Fix relative indentation when pasting content copied from outside Zed (#25300)

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

Release Notes:

- Fixed incorrect indentation when pasting multi-line content that was
copied from another app.
This commit is contained in:
Max Brunsfeld 2025-02-20 17:25:33 -08:00 committed by GitHub
parent ee1a559827
commit c31c638006
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 233 additions and 190 deletions

View file

@ -393,9 +393,17 @@ pub enum AutoindentMode {
/// Apply the same indentation adjustment to all of the lines
/// in a given insertion.
Block {
/// The original indentation level of the first line of each
/// insertion, if it has been copied.
original_indent_columns: Vec<u32>,
/// The original start column of each insertion, if it was
/// copied from elsewhere.
///
/// Knowing this start column makes it possible to preserve the
/// relative indentation of every line in the insertion from
/// when it was copied.
///
/// If the start column is `a`, and the first line of insertion
/// is then auto-indented to column `b`, then every other line of
/// the insertion will be auto-indented to column `b - a`
original_start_columns: Vec<u32>,
},
}
@ -2191,16 +2199,16 @@ impl Buffer {
let mut original_indent_column = None;
if let AutoindentMode::Block {
original_indent_columns,
original_start_columns,
} = &mode
{
original_indent_column =
Some(original_indent_columns.get(ix).copied().unwrap_or_else(|| {
indent_size_for_text(
original_indent_column = Some(
original_start_columns.get(ix).copied().unwrap_or(0)
+ indent_size_for_text(
new_text[range_of_insertion_to_indent.clone()].chars(),
)
.len
}));
.len,
);
// Avoid auto-indenting the line after the edit.
if new_text[range_of_insertion_to_indent.clone()].ends_with('\n') {

View file

@ -1657,7 +1657,7 @@ fn test_autoindent_block_mode(cx: &mut App) {
buffer.edit(
[(Point::new(2, 0)..Point::new(2, 0), inserted_text.clone())],
Some(AutoindentMode::Block {
original_indent_columns: original_indent_columns.clone(),
original_start_columns: original_indent_columns.clone(),
}),
cx,
);
@ -1685,7 +1685,7 @@ fn test_autoindent_block_mode(cx: &mut App) {
buffer.edit(
[(Point::new(2, 8)..Point::new(2, 8), inserted_text)],
Some(AutoindentMode::Block {
original_indent_columns: original_indent_columns.clone(),
original_start_columns: original_indent_columns.clone(),
}),
cx,
);
@ -1734,7 +1734,7 @@ fn test_autoindent_block_mode_without_original_indent_columns(cx: &mut App) {
buffer.edit(
[(Point::new(2, 0)..Point::new(2, 0), inserted_text)],
Some(AutoindentMode::Block {
original_indent_columns: original_indent_columns.clone(),
original_start_columns: original_indent_columns.clone(),
}),
cx,
);
@ -1765,7 +1765,7 @@ fn test_autoindent_block_mode_without_original_indent_columns(cx: &mut App) {
buffer.edit(
[(Point::new(2, 12)..Point::new(2, 12), inserted_text)],
Some(AutoindentMode::Block {
original_indent_columns: Vec::new(),
original_start_columns: Vec::new(),
}),
cx,
);
@ -1821,7 +1821,7 @@ fn test_autoindent_block_mode_multiple_adjacent_ranges(cx: &mut App) {
(ranges_to_replace[2].clone(), "fn three() {\n 103\n}\n"),
],
Some(AutoindentMode::Block {
original_indent_columns: vec![0, 0, 0],
original_start_columns: vec![0, 0, 0],
}),
cx,
);