From 00097df0d585c65103e1c1fd170cce3a28c631aa Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Fri, 18 Jul 2025 03:24:20 -0700 Subject: [PATCH] Improve C/C++ indentation flow for single statement blocks (#34549) Before this, indentation did not automatically increase after if/for/while/do/else statements in C++, and only increased after if/for in C. This led to Zed using last line logic when inserting lines *after* the indented statement, as well as not indenting the statement itself, resulting in irregular indentation during typing. Just adding indentation (similar to C) creates a new problem: now if a scope is started with a brace on a new line, that brace is indented. Thus we need to deindent it. Using else_clause in the indent guide results in the else statement being indented forward as well, so we need to deindent that too. Note: the most significant issue for me is the one where indentation jumps forward when inserting lines after indented lines. Unfortunately, it appears that fixing that issue requires all of these other changes. I would have preferred a simpler fix, but I'm not sure if disabling last line behavior for C/C++ is appropriate as it probably breaks something else, like cases where the file is incomplete and the statements can't be parsed properly. Editing flow before this change: [Screencast From 2025-07-16 08-31-36.webm](https://github.com/user-attachments/assets/3dea86c5-47bd-47c2-aee8-b0aa613948e6) Editing flow after this change: [Screencast From 2025-07-16 08-35-36.webm](https://github.com/user-attachments/assets/7ef23e60-1ee3-49fd-90f9-d53f909ca674) (note: the "else" snippet is completely breaking the flow here, but I think that comes from clangd by default? Unfortunately I haven't found a way to disable it cleanly but that is a separate problem that happens right now too.) Release Notes: - Improve indentation during typing for C/C++ around if/for/while/do blocks --- crates/languages/src/c/config.toml | 4 ++++ crates/languages/src/c/indents.scm | 10 ++++++++++ crates/languages/src/cpp/config.toml | 4 ++++ crates/languages/src/cpp/indents.scm | 12 ++++++++++++ 4 files changed, 30 insertions(+) diff --git a/crates/languages/src/c/config.toml b/crates/languages/src/c/config.toml index 08cd100f4d4dcb7c00eee33a2491864283986a82..78213da5be43da1ba13e1566a72f552f7db3986c 100644 --- a/crates/languages/src/c/config.toml +++ b/crates/languages/src/c/config.toml @@ -2,6 +2,10 @@ name = "C" grammar = "c" path_suffixes = ["c"] line_comments = ["// "] +decrease_indent_patterns = [ + { pattern = "^\\s*\\{.*\\}?\\s*$", valid_after = ["if", "for", "while", "do", "switch", "else"] }, + { pattern = "^\\s*else\\s*$", valid_after = ["if"] } +] autoclose_before = ";:.,=}])>" brackets = [ { start = "{", end = "}", close = true, newline = true }, diff --git a/crates/languages/src/c/indents.scm b/crates/languages/src/c/indents.scm index fa40ce215e358a067f48997ab4d870174f1ea479..3b6d5135abe593656d4134b309bf5d43f54a8f59 100644 --- a/crates/languages/src/c/indents.scm +++ b/crates/languages/src/c/indents.scm @@ -3,7 +3,17 @@ (assignment_expression) (if_statement) (for_statement) + (while_statement) + (do_statement) + (else_clause) ] @indent (_ "{" "}" @end) @indent (_ "(" ")" @end) @indent + +(if_statement) @start.if +(for_statement) @start.for +(while_statement) @start.while +(do_statement) @start.do +(switch_statement) @start.switch +(else_clause) @start.else diff --git a/crates/languages/src/cpp/config.toml b/crates/languages/src/cpp/config.toml index a81cbe09cde970398719eef8af75864635b3e43b..1e283816053f27fa39d985e79bc4e7d89db4477a 100644 --- a/crates/languages/src/cpp/config.toml +++ b/crates/languages/src/cpp/config.toml @@ -2,6 +2,10 @@ name = "C++" grammar = "cpp" path_suffixes = ["cc", "hh", "cpp", "h", "hpp", "cxx", "hxx", "c++", "ipp", "inl", "ixx", "cu", "cuh", "C", "H"] line_comments = ["// ", "/// ", "//! "] +decrease_indent_patterns = [ + { pattern = "^\\s*\\{.*\\}?\\s*$", valid_after = ["if", "for", "while", "do", "switch", "else"] }, + { pattern = "^\\s*else\\s*$", valid_after = ["if"] } +] autoclose_before = ";:.,=}])>" brackets = [ { start = "{", end = "}", close = true, newline = true }, diff --git a/crates/languages/src/cpp/indents.scm b/crates/languages/src/cpp/indents.scm index a17f4c4821e1ff096e9977c28801eeba581d8b17..d95dfe178cbada6836cb14bca997619fe2a319b3 100644 --- a/crates/languages/src/cpp/indents.scm +++ b/crates/languages/src/cpp/indents.scm @@ -1,7 +1,19 @@ [ (field_expression) (assignment_expression) + (if_statement) + (for_statement) + (while_statement) + (do_statement) + (else_clause) ] @indent (_ "{" "}" @end) @indent (_ "(" ")" @end) @indent + +(if_statement) @start.if +(for_statement) @start.for +(while_statement) @start.while +(do_statement) @start.do +(switch_statement) @start.switch +(else_clause) @start.else