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
|
@ -696,10 +696,6 @@ pub struct LanguageConfig {
|
|||
#[serde(default)]
|
||||
#[schemars(schema_with = "bracket_pair_config_json_schema")]
|
||||
pub brackets: BracketPairConfig,
|
||||
/// If set to true, indicates the language uses significant whitespace/indentation
|
||||
/// for syntax structure (like Python) rather than brackets/braces for code blocks.
|
||||
#[serde(default)]
|
||||
pub significant_indentation: bool,
|
||||
/// If set to true, auto indentation uses last non empty line to determine
|
||||
/// the indentation level for a new line.
|
||||
#[serde(default = "auto_indent_using_last_non_empty_line_default")]
|
||||
|
@ -717,6 +713,12 @@ pub struct LanguageConfig {
|
|||
#[serde(default, deserialize_with = "deserialize_regex")]
|
||||
#[schemars(schema_with = "regex_json_schema")]
|
||||
pub decrease_indent_pattern: Option<Regex>,
|
||||
/// A list of rules for decreasing indentation. Each rule pairs a regex with a set of valid
|
||||
/// "block-starting" tokens. When a line matches a pattern, its indentation is aligned with
|
||||
/// the most recent line that began with a corresponding token. This enables context-aware
|
||||
/// outdenting, like aligning an `else` with its `if`.
|
||||
#[serde(default)]
|
||||
pub decrease_indent_patterns: Vec<DecreaseIndentConfig>,
|
||||
/// A list of characters that trigger the automatic insertion of a closing
|
||||
/// bracket when they immediately precede the point where an opening
|
||||
/// bracket is inserted.
|
||||
|
@ -776,6 +778,15 @@ pub struct LanguageConfig {
|
|||
pub documentation: Option<DocumentationConfig>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Default, JsonSchema)]
|
||||
pub struct DecreaseIndentConfig {
|
||||
#[serde(default, deserialize_with = "deserialize_regex")]
|
||||
#[schemars(schema_with = "regex_json_schema")]
|
||||
pub pattern: Option<Regex>,
|
||||
#[serde(default)]
|
||||
pub valid_after: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Default, JsonSchema)]
|
||||
pub struct LanguageMatcher {
|
||||
/// Given a list of `LanguageConfig`'s, the language of a file can be determined based on the path extension matching any of the `path_suffixes`.
|
||||
|
@ -899,6 +910,7 @@ impl Default for LanguageConfig {
|
|||
auto_indent_on_paste: None,
|
||||
increase_indent_pattern: Default::default(),
|
||||
decrease_indent_pattern: Default::default(),
|
||||
decrease_indent_patterns: Default::default(),
|
||||
autoclose_before: Default::default(),
|
||||
line_comments: Default::default(),
|
||||
block_comment: Default::default(),
|
||||
|
@ -914,7 +926,6 @@ impl Default for LanguageConfig {
|
|||
jsx_tag_auto_close: None,
|
||||
completion_query_characters: Default::default(),
|
||||
debuggers: Default::default(),
|
||||
significant_indentation: Default::default(),
|
||||
documentation: None,
|
||||
}
|
||||
}
|
||||
|
@ -1092,6 +1103,7 @@ struct IndentConfig {
|
|||
start_capture_ix: Option<u32>,
|
||||
end_capture_ix: Option<u32>,
|
||||
outdent_capture_ix: Option<u32>,
|
||||
suffixed_start_captures: HashMap<u32, SharedString>,
|
||||
}
|
||||
|
||||
pub struct OutlineConfig {
|
||||
|
@ -1522,6 +1534,14 @@ impl Language {
|
|||
("outdent", &mut outdent_capture_ix),
|
||||
],
|
||||
);
|
||||
|
||||
let mut suffixed_start_captures = HashMap::default();
|
||||
for (ix, name) in query.capture_names().iter().enumerate() {
|
||||
if let Some(suffix) = name.strip_prefix("start.") {
|
||||
suffixed_start_captures.insert(ix as u32, suffix.to_owned().into());
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(indent_capture_ix) = indent_capture_ix {
|
||||
grammar.indents_config = Some(IndentConfig {
|
||||
query,
|
||||
|
@ -1529,6 +1549,7 @@ impl Language {
|
|||
start_capture_ix,
|
||||
end_capture_ix,
|
||||
outdent_capture_ix,
|
||||
suffixed_start_captures,
|
||||
});
|
||||
}
|
||||
Ok(self)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue