From ad5c50851710711fa1d62708633d7bae92f82fae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Kvalsvik?= Date: Tue, 19 Nov 2024 08:01:01 +0100 Subject: [PATCH] Indent compounds c-ts-mode when { is not BOL Properly indent the body of compound expressions, even when then compound expression is not at the beginning of line and the parent is not an if/for/while/etc., and matches the behavior of c-mode. This fixes a problem that is common with macros and in testing frameworks. For example, you expect this to indent: TEST_CASE(1) { assert (...); } If the compound statement is the function body itself, don't apply this new rule and instead guide by the parent and first sibling. I'm sure there are subtle interactions that aren't handled properly by checking for "function_definition" rather than something more general, but it does fix the test case and the check can be improved as more cases are found. * lisp/progmodes/c-ts-mode.el (c-ts-mode--parent-is-not-top-compound): New function. (c-ts-mode--indent-styles): Use it. * test/lisp/progmodes/c-ts-mode-resources/indent.erts: New compound statement test. --- lisp/progmodes/c-ts-mode.el | 8 +++++ .../progmodes/c-ts-mode-resources/indent.erts | 30 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index 3823c553fda..80233e90241 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -402,6 +402,11 @@ c-ts-mode--first-sibling (treesit-node-start parent) (line-end-position)))))) +(defun c-ts-mode--parent-is-not-top-compound (_n parent &rest _) + "Matches when PARENT is not the top level compound statement, +the {} that immediately follows the signature." + (not (equal "function_definition" (treesit-node-type (treesit-node-parent parent))))) + (defun c-ts-mode--indent-styles (mode) "Indent rules supported by `c-ts-mode'. MODE is either `c' or `cpp'." @@ -478,6 +483,7 @@ c-ts-mode--indent-styles ;; Closing bracket. This should be before initializer_list ;; (and probably others) rule because that rule (and other ;; similar rules) will match the closing bracket. (Bug#61398) + ((and (node-is "}") c-ts-mode--parent-is-not-top-compound) parent-bol 0) ((node-is "}") standalone-parent 0) ,@(when (eq mode 'cpp) '(((node-is "access_specifier") parent-bol 0) @@ -497,6 +503,8 @@ c-ts-mode--indent-styles ((parent-is "field_declaration_list") c-ts-mode--anchor-prev-sibling 0) ;; Statement in {} blocks. + ((and (parent-is "compound_statement") c-ts-mode--parent-is-not-top-compound) + parent-bol c-ts-mode-indent-offset) ((or (and (parent-is "compound_statement") ;; If the previous sibling(s) are not on their ;; own line, indent as if this node is the first diff --git a/test/lisp/progmodes/c-ts-mode-resources/indent.erts b/test/lisp/progmodes/c-ts-mode-resources/indent.erts index 2f3540c3970..61e61677ed7 100644 --- a/test/lisp/progmodes/c-ts-mode-resources/indent.erts +++ b/test/lisp/progmodes/c-ts-mode-resources/indent.erts @@ -223,6 +223,36 @@ make_pair(int long_identifier_a[], int long_identifier_b[], =-=-= +Name: Compound Statement after code + +=-= +#define IOTA(var, n) for (int var = 0; var != (n); ++var) +int main() +{ +IOTA (v, 10) { +printf("%d ", v); +} + +const char *msg = "Hello, world!"; { +puts("Hello, world!"); +} +} + +=-= +#define IOTA(var, n) for (int var = 0; var != (n); ++var) +int main() +{ + IOTA (v, 10) { + printf("%d ", v); + } + + const char *msg = "Hello, world!"; { + puts("Hello, world!"); + } +} + +=-=-= + Name: Switch-Case statement =-= -- 2.39.5