In most languages, use prev non-empty line as basis for preserving indent
This commit is contained in:
parent
431d71fe92
commit
fae1cc36d6
2 changed files with 45 additions and 16 deletions
|
@ -1583,7 +1583,7 @@ impl BufferSnapshot {
|
||||||
..Point::new(row_range.end, 0).to_ts_point(),
|
..Point::new(row_range.end, 0).to_ts_point(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut indentation_ranges = Vec::<Range<Point>>::new();
|
let mut indent_ranges = Vec::<Range<Point>>::new();
|
||||||
for mat in query_cursor.matches(
|
for mat in query_cursor.matches(
|
||||||
indents_query,
|
indents_query,
|
||||||
self.tree.as_ref()?.root_node(),
|
self.tree.as_ref()?.root_node(),
|
||||||
|
@ -1606,10 +1606,10 @@ impl BufferSnapshot {
|
||||||
}
|
}
|
||||||
|
|
||||||
let range = start..end;
|
let range = start..end;
|
||||||
match indentation_ranges.binary_search_by_key(&range.start, |r| r.start) {
|
match indent_ranges.binary_search_by_key(&range.start, |r| r.start) {
|
||||||
Err(ix) => indentation_ranges.insert(ix, range),
|
Err(ix) => indent_ranges.insert(ix, range),
|
||||||
Ok(ix) => {
|
Ok(ix) => {
|
||||||
let prev_range = &mut indentation_ranges[ix];
|
let prev_range = &mut indent_ranges[ix];
|
||||||
prev_range.end = prev_range.end.max(range.end);
|
prev_range.end = prev_range.end.max(range.end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1617,7 +1617,7 @@ impl BufferSnapshot {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the suggested indentation increases and decreased based on regexes.
|
// Find the suggested indentation increases and decreased based on regexes.
|
||||||
let mut indent_changes = Vec::<(u32, Ordering)>::new();
|
let mut indent_change_rows = Vec::<(u32, Ordering)>::new();
|
||||||
self.for_each_line(
|
self.for_each_line(
|
||||||
Point::new(prev_non_blank_row.unwrap_or(row_range.start), 0)
|
Point::new(prev_non_blank_row.unwrap_or(row_range.start), 0)
|
||||||
..Point::new(row_range.end, 0),
|
..Point::new(row_range.end, 0),
|
||||||
|
@ -1627,20 +1627,24 @@ impl BufferSnapshot {
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or(false, |regex| regex.is_match(line))
|
.map_or(false, |regex| regex.is_match(line))
|
||||||
{
|
{
|
||||||
indent_changes.push((row, Ordering::Less));
|
indent_change_rows.push((row, Ordering::Less));
|
||||||
}
|
}
|
||||||
if config
|
if config
|
||||||
.increase_indent_pattern
|
.increase_indent_pattern
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or(false, |regex| regex.is_match(line))
|
.map_or(false, |regex| regex.is_match(line))
|
||||||
{
|
{
|
||||||
indent_changes.push((row + 1, Ordering::Greater));
|
indent_change_rows.push((row + 1, Ordering::Greater));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut indent_changes = indent_changes.into_iter().peekable();
|
let mut indent_changes = indent_change_rows.into_iter().peekable();
|
||||||
let mut prev_row = row_range.start.saturating_sub(1);
|
let mut prev_row = if config.auto_indent_using_last_non_empty_line {
|
||||||
|
prev_non_blank_row.unwrap_or(0)
|
||||||
|
} else {
|
||||||
|
row_range.start.saturating_sub(1)
|
||||||
|
};
|
||||||
let mut prev_row_start = Point::new(prev_row, self.indent_size_for_line(prev_row).len);
|
let mut prev_row_start = Point::new(prev_row, self.indent_size_for_line(prev_row).len);
|
||||||
Some(row_range.map(move |row| {
|
Some(row_range.map(move |row| {
|
||||||
let row_start = Point::new(row, self.indent_size_for_line(row).len);
|
let row_start = Point::new(row, self.indent_size_for_line(row).len);
|
||||||
|
@ -1662,7 +1666,7 @@ impl BufferSnapshot {
|
||||||
indent_changes.next();
|
indent_changes.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
for range in &indentation_ranges {
|
for range in &indent_ranges {
|
||||||
if range.start.row >= row {
|
if range.start.row >= row {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -442,31 +442,56 @@ mod tests {
|
||||||
let mut buffer = Buffer::new(0, "", cx).with_language(Arc::new(language), cx);
|
let mut buffer = Buffer::new(0, "", cx).with_language(Arc::new(language), cx);
|
||||||
let size = IndentSize::spaces(2);
|
let size = IndentSize::spaces(2);
|
||||||
|
|
||||||
// start with empty function
|
|
||||||
buffer.edit_with_autoindent([(0..0, "fn a() {}")], size, cx);
|
|
||||||
|
|
||||||
// indent between braces
|
// indent between braces
|
||||||
|
buffer.set_text("fn a() {}", cx);
|
||||||
let ix = buffer.len() - 1;
|
let ix = buffer.len() - 1;
|
||||||
buffer.edit_with_autoindent([(ix..ix, "\n\n")], size, cx);
|
buffer.edit_with_autoindent([(ix..ix, "\n\n")], size, cx);
|
||||||
assert_eq!(buffer.text(), "fn a() {\n \n}");
|
assert_eq!(buffer.text(), "fn a() {\n \n}");
|
||||||
|
|
||||||
// indent field expression
|
// indent between braces, even after empty lines
|
||||||
|
buffer.set_text("fn a() {\n\n\n}", cx);
|
||||||
|
let ix = buffer.len() - 2;
|
||||||
|
buffer.edit_with_autoindent([(ix..ix, "\n")], size, cx);
|
||||||
|
assert_eq!(buffer.text(), "fn a() {\n\n\n \n}");
|
||||||
|
|
||||||
|
// indent a line that continues a field expression
|
||||||
|
buffer.set_text("fn a() {\n \n}", cx);
|
||||||
let ix = buffer.len() - 2;
|
let ix = buffer.len() - 2;
|
||||||
buffer.edit_with_autoindent([(ix..ix, "b\n.c")], size, cx);
|
buffer.edit_with_autoindent([(ix..ix, "b\n.c")], size, cx);
|
||||||
assert_eq!(buffer.text(), "fn a() {\n b\n .c\n}");
|
assert_eq!(buffer.text(), "fn a() {\n b\n .c\n}");
|
||||||
|
|
||||||
// indent chained field expression preceded by blank line
|
// indent further lines that continue the field expression, even after empty lines
|
||||||
let ix = buffer.len() - 2;
|
let ix = buffer.len() - 2;
|
||||||
buffer.edit_with_autoindent([(ix..ix, "\n\n.d")], size, cx);
|
buffer.edit_with_autoindent([(ix..ix, "\n\n.d")], size, cx);
|
||||||
assert_eq!(buffer.text(), "fn a() {\n b\n .c\n \n .d\n}");
|
assert_eq!(buffer.text(), "fn a() {\n b\n .c\n \n .d\n}");
|
||||||
|
|
||||||
// dedent line after the field expression
|
// dedent the line after the field expression
|
||||||
let ix = buffer.len() - 2;
|
let ix = buffer.len() - 2;
|
||||||
buffer.edit_with_autoindent([(ix..ix, ";\ne")], size, cx);
|
buffer.edit_with_autoindent([(ix..ix, ";\ne")], size, cx);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
buffer.text(),
|
buffer.text(),
|
||||||
"fn a() {\n b\n .c\n \n .d;\n e\n}"
|
"fn a() {\n b\n .c\n \n .d;\n e\n}"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// indent inside a struct within a call
|
||||||
|
buffer.set_text("const a: B = c(D {});", cx);
|
||||||
|
let ix = buffer.len() - 3;
|
||||||
|
buffer.edit_with_autoindent([(ix..ix, "\n\n")], size, cx);
|
||||||
|
assert_eq!(buffer.text(), "const a: B = c(D {\n \n});");
|
||||||
|
|
||||||
|
// indent further inside a nested call
|
||||||
|
let ix = buffer.len() - 4;
|
||||||
|
buffer.edit_with_autoindent([(ix..ix, "e: f(\n\n)")], size, cx);
|
||||||
|
assert_eq!(buffer.text(), "const a: B = c(D {\n e: f(\n \n )\n});");
|
||||||
|
|
||||||
|
// keep that indent after an empty line
|
||||||
|
let ix = buffer.len() - 8;
|
||||||
|
buffer.edit_with_autoindent([(ix..ix, "\n")], size, cx);
|
||||||
|
assert_eq!(
|
||||||
|
buffer.text(),
|
||||||
|
"const a: B = c(D {\n e: f(\n \n \n )\n});"
|
||||||
|
);
|
||||||
|
|
||||||
buffer
|
buffer
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue