Fix error in autoindent range calculation

This commit is contained in:
Max Brunsfeld 2022-07-28 11:51:03 -07:00
parent f547c268ce
commit b1b252ee45

View File

@ -237,7 +237,12 @@ struct AutoindentRequest {
#[derive(Clone)] #[derive(Clone)]
struct AutoindentRequestEntry { struct AutoindentRequestEntry {
/// A range of the buffer whose indentation should be adjusted.
range: Range<Anchor>, range: Range<Anchor>,
/// Whether or not these lines should be considered brand new, for the
/// purpose of auto-indent. When text is not new, its indentation will
/// only be adjusted if the suggested indentation level has *changed*
/// since the edit was made.
first_line_is_new: bool, first_line_is_new: bool,
} }
@ -1216,41 +1221,34 @@ impl Buffer {
.zip(&edit_operation.as_edit().unwrap().new_text) .zip(&edit_operation.as_edit().unwrap().new_text)
.map(|((range, _), new_text)| { .map(|((range, _), new_text)| {
let new_text_len = new_text.len(); let new_text_len = new_text.len();
let first_newline_ix = new_text.find('\n');
let old_start = range.start.to_point(&before_edit); let old_start = range.start.to_point(&before_edit);
let new_start = (delta + range.start as isize) as usize; let new_start = (delta + range.start as isize) as usize;
delta += new_text_len as isize - (range.end as isize - range.start as isize); delta += new_text_len as isize - (range.end as isize - range.start as isize);
let mut relative_range = 0..new_text_len; let mut range_of_insertion_to_indent = 0..new_text_len;
let mut first_line_is_new = false; let mut first_line_is_new = false;
// When inserting multiple lines of text at the beginning of a line, // When inserting an entire line at the beginning of an existing line,
// treat the insertion as new. // treat the insertion as new.
if first_newline_ix.is_some() if new_text.contains('\n')
&& old_start.column < before_edit.indent_size_for_line(old_start.row).len && old_start.column <= before_edit.indent_size_for_line(old_start.row).len
{ {
first_line_is_new = true; first_line_is_new = true;
} }
// When inserting a newline at the end of an existing line, avoid
// auto-indenting that existing line, but treat the subsequent text as new. // Avoid auto-indenting lines before and after the insertion.
else if first_newline_ix == Some(0) if new_text[range_of_insertion_to_indent.clone()].starts_with('\n') {
&& old_start.column == before_edit.line_len(old_start.row) range_of_insertion_to_indent.start += 1;
{
relative_range.start += 1;
first_line_is_new = true; first_line_is_new = true;
} }
// Avoid auto-indenting subsequent lines when inserting text with trailing if new_text[range_of_insertion_to_indent.clone()].ends_with('\n') {
// newlines range_of_insertion_to_indent.end -= 1;
while !relative_range.is_empty()
&& new_text[relative_range.clone()].ends_with('\n')
{
relative_range.end -= 1;
} }
AutoindentRequestEntry { AutoindentRequestEntry {
first_line_is_new, first_line_is_new,
range: before_edit.anchor_before(new_start + relative_range.start) range: self.anchor_before(new_start + range_of_insertion_to_indent.start)
..self.anchor_after(new_start + relative_range.end), ..self.anchor_after(new_start + range_of_insertion_to_indent.end),
} }
}) })
.collect(); .collect();