language: Add context-aware decrease indent for Python (#33370)
Closes #33238, follow-up to https://github.com/zed-industries/zed/pull/29625. Changes: - Removed `significant_indentation`, which was the way to introduce indentation scoping in languages like Python. However, it turned out to be unnecessarily complicated to define and maintain. - Introduced `decrease_indent_patterns`, which takes a `pattern` keyword to automatically outdent and `valid_after` keywords to treat as valid code points to snap to. The outdent happens to the most recent `valid_after` keyword that also has less or equal indentation than the currently typed keyword. Fixes: 1. In Python, typing `except`, `finally`, `else`, and so on now automatically indents intelligently based on the context in which it appears. For instance: ```py try: if a == 1: try: b = 2 ^ # <-- typing "except:" here would indent it to inner try block ``` but, ```py try: if a == 1: try: b = 2 ^ # <-- typing "except:" here would indent it to outer try block ``` 2. Fixes comments not maintaining indent. Release Notes: - Improved auto outdent for Python while typing keywords like `except`, `else`, `finally`, etc. - Fixed the issue where comments in Python would not maintain their indentation.
This commit is contained in:
parent
1753432406
commit
d09c7eb317
6 changed files with 211 additions and 181 deletions
|
@ -21771,9 +21771,9 @@ async fn test_tab_in_leading_whitespace_auto_indents_for_python(cx: &mut TestApp
|
|||
cx.set_state(indoc! {"
|
||||
def main():
|
||||
ˇ try:
|
||||
ˇ fetch()
|
||||
ˇ fetch()
|
||||
ˇ except ValueError:
|
||||
ˇ handle_error()
|
||||
ˇ handle_error()
|
||||
ˇ else:
|
||||
ˇ match value:
|
||||
ˇ case _:
|
||||
|
@ -21901,74 +21901,101 @@ async fn test_outdent_after_input_for_python(cx: &mut TestAppContext) {
|
|||
finally:ˇ
|
||||
"});
|
||||
|
||||
// TODO: test `except` auto outdents when typed inside `try` block right after for block
|
||||
// cx.set_state(indoc! {"
|
||||
// def main():
|
||||
// try:
|
||||
// for i in range(n):
|
||||
// pass
|
||||
// ˇ
|
||||
// "});
|
||||
// cx.update_editor(|editor, window, cx| {
|
||||
// editor.handle_input("except:", window, cx);
|
||||
// });
|
||||
// cx.assert_editor_state(indoc! {"
|
||||
// def main():
|
||||
// try:
|
||||
// for i in range(n):
|
||||
// pass
|
||||
// except:ˇ
|
||||
// "});
|
||||
// test `else` does not outdents when typed inside `except` block right after for block
|
||||
cx.set_state(indoc! {"
|
||||
def main():
|
||||
try:
|
||||
i = 2
|
||||
except:
|
||||
for i in range(n):
|
||||
pass
|
||||
ˇ
|
||||
"});
|
||||
cx.update_editor(|editor, window, cx| {
|
||||
editor.handle_input("else:", window, cx);
|
||||
});
|
||||
cx.assert_editor_state(indoc! {"
|
||||
def main():
|
||||
try:
|
||||
i = 2
|
||||
except:
|
||||
for i in range(n):
|
||||
pass
|
||||
else:ˇ
|
||||
"});
|
||||
|
||||
// TODO: test `else` auto outdents when typed inside `except` block right after for block
|
||||
// cx.set_state(indoc! {"
|
||||
// def main():
|
||||
// try:
|
||||
// i = 2
|
||||
// except:
|
||||
// for i in range(n):
|
||||
// pass
|
||||
// ˇ
|
||||
// "});
|
||||
// cx.update_editor(|editor, window, cx| {
|
||||
// editor.handle_input("else:", window, cx);
|
||||
// });
|
||||
// cx.assert_editor_state(indoc! {"
|
||||
// def main():
|
||||
// try:
|
||||
// i = 2
|
||||
// except:
|
||||
// for i in range(n):
|
||||
// pass
|
||||
// else:ˇ
|
||||
// "});
|
||||
// test `finally` auto outdents when typed inside `else` block right after for block
|
||||
cx.set_state(indoc! {"
|
||||
def main():
|
||||
try:
|
||||
i = 2
|
||||
except:
|
||||
j = 2
|
||||
else:
|
||||
for i in range(n):
|
||||
pass
|
||||
ˇ
|
||||
"});
|
||||
cx.update_editor(|editor, window, cx| {
|
||||
editor.handle_input("finally:", window, cx);
|
||||
});
|
||||
cx.assert_editor_state(indoc! {"
|
||||
def main():
|
||||
try:
|
||||
i = 2
|
||||
except:
|
||||
j = 2
|
||||
else:
|
||||
for i in range(n):
|
||||
pass
|
||||
finally:ˇ
|
||||
"});
|
||||
|
||||
// TODO: test `finally` auto outdents when typed inside `else` block right after for block
|
||||
// cx.set_state(indoc! {"
|
||||
// def main():
|
||||
// try:
|
||||
// i = 2
|
||||
// except:
|
||||
// j = 2
|
||||
// else:
|
||||
// for i in range(n):
|
||||
// pass
|
||||
// ˇ
|
||||
// "});
|
||||
// cx.update_editor(|editor, window, cx| {
|
||||
// editor.handle_input("finally:", window, cx);
|
||||
// });
|
||||
// cx.assert_editor_state(indoc! {"
|
||||
// def main():
|
||||
// try:
|
||||
// i = 2
|
||||
// except:
|
||||
// j = 2
|
||||
// else:
|
||||
// for i in range(n):
|
||||
// pass
|
||||
// finally:ˇ
|
||||
// "});
|
||||
// test `except` outdents to inner "try" block
|
||||
cx.set_state(indoc! {"
|
||||
def main():
|
||||
try:
|
||||
i = 2
|
||||
if i == 2:
|
||||
try:
|
||||
i = 3
|
||||
ˇ
|
||||
"});
|
||||
cx.update_editor(|editor, window, cx| {
|
||||
editor.handle_input("except:", window, cx);
|
||||
});
|
||||
cx.assert_editor_state(indoc! {"
|
||||
def main():
|
||||
try:
|
||||
i = 2
|
||||
if i == 2:
|
||||
try:
|
||||
i = 3
|
||||
except:ˇ
|
||||
"});
|
||||
|
||||
// test `except` outdents to outer "try" block
|
||||
cx.set_state(indoc! {"
|
||||
def main():
|
||||
try:
|
||||
i = 2
|
||||
if i == 2:
|
||||
try:
|
||||
i = 3
|
||||
ˇ
|
||||
"});
|
||||
cx.update_editor(|editor, window, cx| {
|
||||
editor.handle_input("except:", window, cx);
|
||||
});
|
||||
cx.assert_editor_state(indoc! {"
|
||||
def main():
|
||||
try:
|
||||
i = 2
|
||||
if i == 2:
|
||||
try:
|
||||
i = 3
|
||||
except:ˇ
|
||||
"});
|
||||
|
||||
// test `else` stays at correct indent when typed after `for` block
|
||||
cx.set_state(indoc! {"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue