@@ -80,6 +80,8 @@ pub struct ConfirmCodeAction {
pub struct ToggleComments {
#[serde(default)]
pub advance_downwards: bool,
+ #[serde(default)]
+ pub ignore_indent: bool,
}
#[derive(PartialEq, Clone, Deserialize, Default)]
@@ -8664,14 +8664,22 @@ impl Editor {
let snapshot = this.buffer.read(cx).read(cx);
let empty_str: Arc<str> = Arc::default();
let mut suffixes_inserted = Vec::new();
+ let ignore_indent = action.ignore_indent;
fn comment_prefix_range(
snapshot: &MultiBufferSnapshot,
row: MultiBufferRow,
comment_prefix: &str,
comment_prefix_whitespace: &str,
+ ignore_indent: bool,
) -> Range<Point> {
- let start = Point::new(row.0, snapshot.indent_size_for_line(row).len);
+ let indent_size = if ignore_indent {
+ 0
+ } else {
+ snapshot.indent_size_for_line(row).len
+ };
+
+ let start = Point::new(row.0, indent_size);
let mut line_bytes = snapshot
.bytes_in_range(start..snapshot.max_point())
@@ -8767,7 +8775,16 @@ impl Editor {
}
// If the language has line comments, toggle those.
- let full_comment_prefixes = language.line_comment_prefixes();
+ let mut full_comment_prefixes = language.line_comment_prefixes().to_vec();
+
+ // If ignore_indent is set, trim spaces from the right side of all full_comment_prefixes
+ if ignore_indent {
+ full_comment_prefixes = full_comment_prefixes
+ .into_iter()
+ .map(|s| Arc::from(s.trim_end()))
+ .collect();
+ }
+
if !full_comment_prefixes.is_empty() {
let first_prefix = full_comment_prefixes
.first()
@@ -8794,6 +8811,7 @@ impl Editor {
row,
&prefix[..trimmed_prefix_len],
&prefix[trimmed_prefix_len..],
+ ignore_indent,
)
})
.max_by_key(|range| range.end.column - range.start.column)
@@ -8834,6 +8852,7 @@ impl Editor {
start_row,
comment_prefix,
comment_prefix_whitespace,
+ ignore_indent,
);
let suffix_range = comment_suffix_range(
snapshot.deref(),
@@ -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