Option to insert comment character(s) at the beginning of the line(s) (#19746)

Closes #19459


This PR adds the optional setting to insert comment character(s) at the
beginning of the line(s) instead of after the indentation. It can be
enabled via keybindings:

```
"ctrl-/": ["editor::ToggleComments", { "ignore_indent": true }]
```

As suggested by @notpeter in #19459, this is implemented in
`toggle_comments` (editor.rs) taking the existing `advance_downwards`
option as example.

There's also a test case for the setting, which mimics the test case for
the regular comment toggling behavior.

---

I am not entirely happy with the name `ignore_indent`. The default would
be a double negative now `ignore_indent=false`. A positive wording would
probably easier to understand, but I could not think of anything
concise. `insert_at_line_start` or just `at_line_start` might work, but
didn't convince me either. That said, I am happy to change the name if
there are better ideas.

---

Release Notes:

- Added optional setting to insert comment character(s) at the beginning
of the line(s) instead of after the indentation. It can be used by
changing the default mapping to toggle comments like this: `"ctrl-/":
["editor::ToggleComments", { "ignore_indent": true }]`
This commit is contained in:
Auf keinen Fall Jens 2024-10-31 09:39:57 +01:00 committed by GitHub
parent 7fd334fddb
commit 633b665379
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 149 additions and 2 deletions

View file

@ -8533,6 +8533,131 @@ async fn test_toggle_comment(cx: &mut gpui::TestAppContext) {
"});
}
#[gpui::test]
async fn test_toggle_comment_ignore_indent(cx: &mut gpui::TestAppContext) {
init_test(cx, |_| {});
let mut cx = EditorTestContext::new(cx).await;
let language = Arc::new(Language::new(
LanguageConfig {
line_comments: vec!["// ".into(), "//! ".into(), "/// ".into()],
..Default::default()
},
Some(tree_sitter_rust::LANGUAGE.into()),
));
cx.update_buffer(|buffer, cx| buffer.set_language(Some(language), cx));
let toggle_comments = &ToggleComments {
advance_downwards: false,
ignore_indent: true,
};
// If multiple selections intersect a line, the line is only toggled once.
cx.set_state(indoc! {"
fn a() {
// «b();
// c();
// ˇ» d();
}
"});
cx.update_editor(|e, cx| e.toggle_comments(toggle_comments, cx));
cx.assert_editor_state(indoc! {"
fn a() {
«b();
c();
ˇ» d();
}
"});
// The comment prefix is inserted at the beginning of each line
cx.update_editor(|e, cx| e.toggle_comments(toggle_comments, cx));
cx.assert_editor_state(indoc! {"
fn a() {
// «b();
// c();
// ˇ» d();
}
"});
// If a selection ends at the beginning of a line, that line is not toggled.
cx.set_selections_state(indoc! {"
fn a() {
// b();
// «c();
ˇ»// d();
}
"});
cx.update_editor(|e, cx| e.toggle_comments(toggle_comments, cx));
cx.assert_editor_state(indoc! {"
fn a() {
// b();
«c();
ˇ»// d();
}
"});
// If a selection span a single line and is empty, the line is toggled.
cx.set_state(indoc! {"
fn a() {
a();
b();
ˇ
}
"});
cx.update_editor(|e, cx| e.toggle_comments(toggle_comments, cx));
cx.assert_editor_state(indoc! {"
fn a() {
a();
b();
//ˇ
}
"});
// If a selection span multiple lines, empty lines are not toggled.
cx.set_state(indoc! {"
fn a() {
«a();
c();ˇ»
}
"});
cx.update_editor(|e, cx| e.toggle_comments(toggle_comments, cx));
cx.assert_editor_state(indoc! {"
fn a() {
// «a();
// c();ˇ»
}
"});
// If a selection includes multiple comment prefixes, all lines are uncommented.
cx.set_state(indoc! {"
fn a() {
// «a();
/// b();
//! c();ˇ»
}
"});
cx.update_editor(|e, cx| e.toggle_comments(toggle_comments, cx));
cx.assert_editor_state(indoc! {"
fn a() {
«a();
b();
c();ˇ»
}
"});
}
#[gpui::test]
async fn test_advance_downward_on_toggle_comment(cx: &mut gpui::TestAppContext) {
init_test(cx, |_| {});
@ -8554,6 +8679,7 @@ async fn test_advance_downward_on_toggle_comment(cx: &mut gpui::TestAppContext)
let toggle_comments = &ToggleComments {
advance_downwards: true,
ignore_indent: false,
};
// Single cursor on one line -> advance