Join empty lines with only one space in join_selections (#8989)

* fix: #8977

fixes the issue that lines with only spaces are getting
joined as well

* reverting some renamings

* improve empty line check

* adding integration test

* reverting code block

* fix conditon check for line end

* applying suggested style
This commit is contained in:
TornaxO7 2023-12-06 16:19:54 +01:00 committed by GitHub
parent c3cb1795bf
commit b81aacc5e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 56 additions and 10 deletions

View File

@ -4391,10 +4391,9 @@ fn join_selections_impl(cx: &mut Context, select_space: bool) {
use movement::skip_while; use movement::skip_while;
let (view, doc) = current!(cx.editor); let (view, doc) = current!(cx.editor);
let text = doc.text(); let text = doc.text();
let slice = doc.text().slice(..); let slice = text.slice(..);
let mut changes = Vec::new(); let mut changes = Vec::new();
let fragment = Tendril::from(" ");
for selection in doc.selection(view.id) { for selection in doc.selection(view.id) {
let (start, mut end) = selection.line_range(slice); let (start, mut end) = selection.line_range(slice);
@ -4410,9 +4409,13 @@ fn join_selections_impl(cx: &mut Context, select_space: bool) {
let mut end = text.line_to_char(line + 1); let mut end = text.line_to_char(line + 1);
end = skip_while(slice, end, |ch| matches!(ch, ' ' | '\t')).unwrap_or(end); end = skip_while(slice, end, |ch| matches!(ch, ' ' | '\t')).unwrap_or(end);
// need to skip from start, not end let separator = if end == line_end_char_index(&slice, line + 1) {
let change = (start, end, Some(fragment.clone())); // the joining line contains only space-characters => don't include a whitespace when joining
changes.push(change); None
} else {
Some(Tendril::from(" "))
};
changes.push((start, end, separator));
} }
} }
@ -4424,9 +4427,6 @@ fn join_selections_impl(cx: &mut Context, select_space: bool) {
changes.sort_unstable_by_key(|(from, _to, _text)| *from); changes.sort_unstable_by_key(|(from, _to, _text)| *from);
changes.dedup(); changes.dedup();
// TODO: joining multiple empty lines should be replaced by a single space.
// need to merge change ranges that touch
// select inserted spaces // select inserted spaces
let transaction = if select_space { let transaction = if select_space {
let ranges: SmallVec<_> = changes let ranges: SmallVec<_> = changes
@ -4438,9 +4438,9 @@ fn join_selections_impl(cx: &mut Context, select_space: bool) {
}) })
.collect(); .collect();
let selection = Selection::new(ranges, 0); let selection = Selection::new(ranges, 0);
Transaction::change(doc.text(), changes.into_iter()).with_selection(selection) Transaction::change(text, changes.into_iter()).with_selection(selection)
} else { } else {
Transaction::change(doc.text(), changes.into_iter()) Transaction::change(text, changes.into_iter())
}; };
doc.apply(&transaction, view.id); doc.apply(&transaction, view.id);

View File

@ -480,3 +480,49 @@ fn bar() {#(\n|)#\
Ok(()) Ok(())
} }
#[tokio::test(flavor = "multi_thread")]
async fn test_join_selections() -> anyhow::Result<()> {
// normal join
test((
platform_line(indoc! {"\
#[a|]#bc
def
"}),
"J",
platform_line(indoc! {"\
#[a|]#bc def
"}),
))
.await?;
// join with empty line
test((
platform_line(indoc! {"\
#[a|]#bc
def
"}),
"JJ",
platform_line(indoc! {"\
#[a|]#bc def
"}),
))
.await?;
// join with additional space in non-empty line
test((
platform_line(indoc! {"\
#[a|]#bc
def
"}),
"JJ",
platform_line(indoc! {"\
#[a|]#bc def
"}),
))
.await?;
Ok(())
}