Support indent regex with inline comments in Python (#37903)

ImFeH2 created

Closes #36491

This issue is caused by the Python language configuration treating
compound statements (such as for loops and if statements) that end with
an inline comment as not requiring an increased indent.

Release Notes:

- python: Correctly indent lines starting the blocks (for, finally, if,
else, try) that have trailing comments.

Change summary

crates/languages/src/python.rs          | 20 ++++++++++++++++++++
crates/languages/src/python/config.toml | 10 +++++-----
2 files changed, 25 insertions(+), 5 deletions(-)

Detailed changes

crates/languages/src/python.rs 🔗

@@ -1761,6 +1761,26 @@ mod tests {
                 "def a():\n  \n  if a:\n    b()\n  else:\n    foo(\n    )\n\n"
             );
 
+            // reset to a for loop statement
+            let statement = "for i in range(10):\n  print(i)\n";
+            buffer.edit([(0..buffer.len(), statement)], None, cx);
+
+            // insert single line comment after each line
+            let eol_ixs = statement
+                .char_indices()
+                .filter_map(|(ix, c)| if c == '\n' { Some(ix) } else { None })
+                .collect::<Vec<usize>>();
+            let editions = eol_ixs
+                .iter()
+                .enumerate()
+                .map(|(i, &eol_ix)| (eol_ix..eol_ix, format!(" # comment {}", i + 1)))
+                .collect::<Vec<(std::ops::Range<usize>, String)>>();
+            buffer.edit(editions, Some(AutoindentMode::EachLine), cx);
+            assert_eq!(
+                buffer.text(),
+                "for i in range(10): # comment 1\n  print(i) # comment 2\n"
+            );
+
             // reset to a simple if statement
             buffer.edit([(0..buffer.len(), "if a:\n  b(\n  )")], None, cx);
 

crates/languages/src/python/config.toml 🔗

@@ -28,10 +28,10 @@ brackets = [
 
 auto_indent_using_last_non_empty_line = false
 debuggers = ["Debugpy"]
-increase_indent_pattern = "^[^#].*:\\s*$"
+increase_indent_pattern = "^[^#].*:\\s*(#.*)?$"
 decrease_indent_patterns = [
-  { pattern = "^\\s*elif\\b.*:",    valid_after = ["if", "elif"] },
-  { pattern = "^\\s*else\\b.*:",    valid_after = ["if", "elif", "for", "while", "except"] },
-  { pattern = "^\\s*except\\b.*:",  valid_after = ["try", "except"] },
-  { pattern = "^\\s*finally\\b.*:", valid_after = ["try", "except", "else"] },
+  { pattern = "^\\s*elif\\b.*:\\s*(#.*)?",    valid_after = ["if", "elif"] },
+  { pattern = "^\\s*else\\b.*:\\s*(#.*)?",    valid_after = ["if", "elif", "for", "while", "except"] },
+  { pattern = "^\\s*except\\b.*:\\s*(#.*)?",  valid_after = ["try", "except"] },
+  { pattern = "^\\s*finally\\b.*:\\s*(#.*)?", valid_after = ["try", "except", "else"] },
 ]