Make editor::Rewrap
respect paragraphs (#32046)
Closes #32021 Release Notes: - Changed the behavior of `editor::Rewrap` to not join paragraphs together.
This commit is contained in:
parent
17c3b741ec
commit
8191a5339d
2 changed files with 120 additions and 20 deletions
|
@ -10873,14 +10873,54 @@ impl Editor {
|
|||
pub fn rewrap_impl(&mut self, options: RewrapOptions, cx: &mut Context<Self>) {
|
||||
let buffer = self.buffer.read(cx).snapshot(cx);
|
||||
let selections = self.selections.all::<Point>(cx);
|
||||
let mut selections = selections.iter().peekable();
|
||||
|
||||
// Shrink and split selections to respect paragraph boundaries.
|
||||
let ranges = selections.into_iter().flat_map(|selection| {
|
||||
let language_settings = buffer.language_settings_at(selection.head(), cx);
|
||||
let language_scope = buffer.language_scope_at(selection.head());
|
||||
|
||||
let Some(start_row) = (selection.start.row..=selection.end.row)
|
||||
.find(|row| !buffer.is_line_blank(MultiBufferRow(*row)))
|
||||
else {
|
||||
return vec![];
|
||||
};
|
||||
let Some(end_row) = (selection.start.row..=selection.end.row)
|
||||
.rev()
|
||||
.find(|row| !buffer.is_line_blank(MultiBufferRow(*row)))
|
||||
else {
|
||||
return vec![];
|
||||
};
|
||||
|
||||
let mut row = start_row;
|
||||
let mut ranges = Vec::new();
|
||||
while let Some(blank_row) =
|
||||
(row..end_row).find(|row| buffer.is_line_blank(MultiBufferRow(*row)))
|
||||
{
|
||||
let next_paragraph_start = (blank_row + 1..=end_row)
|
||||
.find(|row| !buffer.is_line_blank(MultiBufferRow(*row)))
|
||||
.unwrap();
|
||||
ranges.push((
|
||||
language_settings.clone(),
|
||||
language_scope.clone(),
|
||||
Point::new(row, 0)..Point::new(blank_row - 1, 0),
|
||||
));
|
||||
row = next_paragraph_start;
|
||||
}
|
||||
ranges.push((
|
||||
language_settings.clone(),
|
||||
language_scope.clone(),
|
||||
Point::new(row, 0)..Point::new(end_row, 0),
|
||||
));
|
||||
|
||||
ranges
|
||||
});
|
||||
|
||||
let mut edits = Vec::new();
|
||||
let mut rewrapped_row_ranges = Vec::<RangeInclusive<u32>>::new();
|
||||
|
||||
while let Some(selection) = selections.next() {
|
||||
let mut start_row = selection.start.row;
|
||||
let mut end_row = selection.end.row;
|
||||
for (language_settings, language_scope, range) in ranges {
|
||||
let mut start_row = range.start.row;
|
||||
let mut end_row = range.end.row;
|
||||
|
||||
// Skip selections that overlap with a range that has already been rewrapped.
|
||||
let selection_range = start_row..end_row;
|
||||
|
@ -10891,7 +10931,7 @@ impl Editor {
|
|||
continue;
|
||||
}
|
||||
|
||||
let tab_size = buffer.language_settings_at(selection.head(), cx).tab_size;
|
||||
let tab_size = language_settings.tab_size;
|
||||
|
||||
// Since not all lines in the selection may be at the same indent
|
||||
// level, choose the indent size that is the most common between all
|
||||
|
@ -10922,25 +10962,20 @@ impl Editor {
|
|||
let mut line_prefix = indent_size.chars().collect::<String>();
|
||||
|
||||
let mut inside_comment = false;
|
||||
if let Some(comment_prefix) =
|
||||
buffer
|
||||
.language_scope_at(selection.head())
|
||||
.and_then(|language| {
|
||||
language
|
||||
.line_comment_prefixes()
|
||||
.iter()
|
||||
.find(|prefix| buffer.contains_str_at(indent_end, prefix))
|
||||
.cloned()
|
||||
})
|
||||
{
|
||||
if let Some(comment_prefix) = language_scope.and_then(|language| {
|
||||
language
|
||||
.line_comment_prefixes()
|
||||
.iter()
|
||||
.find(|prefix| buffer.contains_str_at(indent_end, prefix))
|
||||
.cloned()
|
||||
}) {
|
||||
line_prefix.push_str(&comment_prefix);
|
||||
inside_comment = true;
|
||||
}
|
||||
|
||||
let language_settings = buffer.language_settings_at(selection.head(), cx);
|
||||
let allow_rewrap_based_on_language = match language_settings.allow_rewrap {
|
||||
RewrapBehavior::InComments => inside_comment,
|
||||
RewrapBehavior::InSelections => !selection.is_empty(),
|
||||
RewrapBehavior::InSelections => !range.is_empty(),
|
||||
RewrapBehavior::Anywhere => true,
|
||||
};
|
||||
|
||||
|
@ -10951,11 +10986,12 @@ impl Editor {
|
|||
continue;
|
||||
}
|
||||
|
||||
if selection.is_empty() {
|
||||
if range.is_empty() {
|
||||
'expand_upwards: while start_row > 0 {
|
||||
let prev_row = start_row - 1;
|
||||
if buffer.contains_str_at(Point::new(prev_row, 0), &line_prefix)
|
||||
&& buffer.line_len(MultiBufferRow(prev_row)) as usize > line_prefix.len()
|
||||
&& !buffer.is_line_blank(MultiBufferRow(prev_row))
|
||||
{
|
||||
start_row = prev_row;
|
||||
} else {
|
||||
|
@ -10967,6 +11003,7 @@ impl Editor {
|
|||
let next_row = end_row + 1;
|
||||
if buffer.contains_str_at(Point::new(next_row, 0), &line_prefix)
|
||||
&& buffer.line_len(MultiBufferRow(next_row)) as usize > line_prefix.len()
|
||||
&& !buffer.is_line_blank(MultiBufferRow(next_row))
|
||||
{
|
||||
end_row = next_row;
|
||||
} else {
|
||||
|
|
|
@ -5111,7 +5111,7 @@ async fn test_rewrap(cx: &mut TestAppContext) {
|
|||
nisl venenatis tempus. Donec molestie blandit quam, et porta nunc laoreet in.
|
||||
Integer sit amet scelerisque nisi.
|
||||
"},
|
||||
plaintext_language,
|
||||
plaintext_language.clone(),
|
||||
&mut cx,
|
||||
);
|
||||
|
||||
|
@ -5174,6 +5174,69 @@ async fn test_rewrap(cx: &mut TestAppContext) {
|
|||
&mut cx,
|
||||
);
|
||||
|
||||
assert_rewrap(
|
||||
indoc! {"
|
||||
«ˇone one one one one one one one one one one one one one one one one one one one one one one one one
|
||||
|
||||
two»
|
||||
|
||||
three
|
||||
|
||||
«ˇ\t
|
||||
|
||||
four four four four four four four four four four four four four four four four four four four four»
|
||||
|
||||
«ˇfive five five five five five five five five five five five five five five five five five five five
|
||||
\t»
|
||||
six six six six six six six six six six six six six six six six six six six six six six six six six
|
||||
"},
|
||||
indoc! {"
|
||||
«ˇone one one one one one one one one one one one one one one one one one one one
|
||||
one one one one one
|
||||
|
||||
two»
|
||||
|
||||
three
|
||||
|
||||
«ˇ\t
|
||||
|
||||
four four four four four four four four four four four four four four four four
|
||||
four four four four»
|
||||
|
||||
«ˇfive five five five five five five five five five five five five five five five
|
||||
five five five five
|
||||
\t»
|
||||
six six six six six six six six six six six six six six six six six six six six six six six six six
|
||||
"},
|
||||
plaintext_language.clone(),
|
||||
&mut cx,
|
||||
);
|
||||
|
||||
assert_rewrap(
|
||||
indoc! {"
|
||||
//ˇ long long long long long long long long long long long long long long long long long long long long long long long long long long long long
|
||||
//ˇ
|
||||
//ˇ long long long long long long long long long long long long long long long long long long long long long long long long long long long long
|
||||
//ˇ short short short
|
||||
int main(void) {
|
||||
return 17;
|
||||
}
|
||||
"},
|
||||
indoc! {"
|
||||
//ˇ long long long long long long long long long long long long long long long
|
||||
// long long long long long long long long long long long long long
|
||||
//ˇ
|
||||
//ˇ long long long long long long long long long long long long long long long
|
||||
//ˇ long long long long long long long long long long long long long short short
|
||||
// short
|
||||
int main(void) {
|
||||
return 17;
|
||||
}
|
||||
"},
|
||||
language_with_c_comments,
|
||||
&mut cx,
|
||||
);
|
||||
|
||||
#[track_caller]
|
||||
fn assert_rewrap(
|
||||
unwrapped_text: &str,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue