Z 1618/extend comments (#2585)

Fixes Z-1618. In the current state, this only works for line comments
such as `//` (and whatever's set in `{language}.toml` as a
line_comment).

Release Notes:

- Comments are now extended on new line.
This commit is contained in:
Piotr Osiewicz 2023-06-07 17:37:02 +02:00 committed by GitHub
parent d5441ba386
commit e94129446d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 88 additions and 29 deletions

View file

@ -2179,40 +2179,72 @@ impl Editor {
indent.len = cmp::min(indent.len, start_point.column);
let start = selection.start;
let end = selection.end;
let is_cursor = start == end;
let language_scope = buffer.language_scope_at(start);
let (comment_delimiter, insert_extra_newline) =
if let Some(language) = &language_scope {
let leading_whitespace_len = buffer
.reversed_chars_at(start)
.take_while(|c| c.is_whitespace() && *c != '\n')
.map(|c| c.len_utf8())
.sum::<usize>();
let mut insert_extra_newline = false;
if let Some(language) = buffer.language_scope_at(start) {
let leading_whitespace_len = buffer
.reversed_chars_at(start)
.take_while(|c| c.is_whitespace() && *c != '\n')
.map(|c| c.len_utf8())
.sum::<usize>();
let trailing_whitespace_len = buffer
.chars_at(end)
.take_while(|c| c.is_whitespace() && *c != '\n')
.map(|c| c.len_utf8())
.sum::<usize>();
let trailing_whitespace_len = buffer
.chars_at(end)
.take_while(|c| c.is_whitespace() && *c != '\n')
.map(|c| c.len_utf8())
.sum::<usize>();
let insert_extra_newline =
language.brackets().any(|(pair, enabled)| {
let pair_start = pair.start.trim_end();
let pair_end = pair.end.trim_start();
insert_extra_newline = language.brackets().any(|(pair, enabled)| {
let pair_start = pair.start.trim_end();
let pair_end = pair.end.trim_start();
enabled
&& pair.newline
&& buffer.contains_str_at(
end + trailing_whitespace_len,
pair_end,
)
&& buffer.contains_str_at(
(start - leading_whitespace_len)
.saturating_sub(pair_start.len()),
pair_start,
)
});
// Comment extension on newline is allowed only for cursor selections
let comment_delimiter =
language.line_comment_prefix().filter(|_| is_cursor);
let comment_delimiter = if let Some(delimiter) = comment_delimiter {
buffer
.buffer_line_for_row(start_point.row)
.is_some_and(|(snapshot, range)| {
snapshot
.chars_for_range(range)
.skip_while(|c| c.is_whitespace())
.take(delimiter.len())
.eq(delimiter.chars())
})
.then(|| delimiter.clone())
} else {
None
};
(comment_delimiter, insert_extra_newline)
} else {
(None, false)
};
enabled
&& pair.newline
&& buffer
.contains_str_at(end + trailing_whitespace_len, pair_end)
&& buffer.contains_str_at(
(start - leading_whitespace_len)
.saturating_sub(pair_start.len()),
pair_start,
)
});
}
let mut new_text = String::with_capacity(1 + indent.len as usize);
new_text.push('\n');
let capacity_for_delimiter = comment_delimiter
.as_deref()
.map(str::len)
.unwrap_or_default();
let mut new_text =
String::with_capacity(1 + capacity_for_delimiter + indent.len as usize);
new_text.push_str("\n");
new_text.extend(indent.chars());
if let Some(delimiter) = &comment_delimiter {
new_text.push_str(&delimiter);
}
if insert_extra_newline {
new_text = new_text.repeat(2);
}

View file

@ -1719,6 +1719,33 @@ async fn test_newline_below(cx: &mut gpui::TestAppContext) {
"});
}
#[gpui::test]
async fn test_newline_comments(cx: &mut gpui::TestAppContext) {
init_test(cx, |settings| {
settings.defaults.tab_size = NonZeroU32::new(4)
});
let language = Arc::new(Language::new(
LanguageConfig {
line_comment: Some("//".into()),
..LanguageConfig::default()
},
None,
));
let mut cx = EditorTestContext::new(cx).await;
cx.update_buffer(|buffer, cx| buffer.set_language(Some(language), cx));
cx.set_state(indoc! {"
// Fooˇ
"});
cx.update_editor(|e, cx| e.newline(&Newline, cx));
cx.assert_editor_state(indoc! {"
// Foo
//ˇ
"});
}
#[gpui::test]
fn test_insert_with_old_selections(cx: &mut TestAppContext) {
init_test(cx, |_| {});