|
From: | Dmitry Gutov |
Subject: | bug#67417: 29.1.50; c-ts-mode syntax issues with no brackets |
Date: | Tue, 28 Nov 2023 17:31:05 +0200 |
User-agent: | Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.13.0 |
On 28/11/2023 08:55, Yuan Fu wrote:
On 11/26/23 6:22 PM, Dmitry Gutov wrote:On 27/11/2023 03:47, Yuan Fu wrote:I pushed two commits which should fix the indentation for "break" after "else", and indentation for empty lines after if/else/for/while in general. The fix for the general case doesn't use the parse tree, since the parse tree is often incomplete when you type if (...) and hit return. Instead it uses a plain regexp match to see if the previous line starts with if/else/for/while. This seems like a reasonable heuristic to use before user types more things, at which point more accurate indentation rules would be used, since the parse tree should be more complete then.Sorry, two counter-examples right away:Type 'elsewhere();' and RET -> the next line is indented 1 level extra, at least until you type some more and then have the line reindented either with pressing TAB or adding semicolon.Type 'for (;;) {}' and RET -> same.The first case is easy to guard against (just check that the next char is either space of opening paren), but the second one less so. OTOH, the second case is likely to have a parse tree without errors, so if we also check for that... the heuristic might work.Well, darn it. And you're right, the second case is a bit hard to check... Well I guess for the moment we can remove this heuristic. (I tried a bit, and checking for no errors is not so easy.)
Maybe it's possible to salvage this heuristic a bit, at least for "else", and as long as it's followed by "}" somewhere (e.g. when electric-pair-mode is used).
diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index 31a9d0fc886..20689dc1862 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -373,8 +373,17 @@ c-ts-mode--indent-styles ;; point on the empty line to be indented; this rule ;; does that. ((and no-node + ;; Could be a matcher 'prev-sibling-p'. + (lambda (_ parent bol &rest _) + (equal + "ERROR" + (treesit-node-type + (treesit-node-prev-sibling + (treesit-node-first-child-for-pos + parent bol) + t)))) (c-ts-mode--prev-line-match - ,(rx (or "if" "else" "while" "do" "for")))) + ,(rx "else" symbol-end))) prev-line c-ts-mode-indent-offset) ((parent-is "translation_unit") column-0 0)The rest of the nodes (if/while/do/for) don't result in parse errors here, as long as the condition in parentheses is typed out correctly.
I tried some additional clauses looking for "previous sibling", checking whether it's for_statement, etc, which ends with "expression statement", and that one is empty... but it a fair amount of code which will likely miss other edge cases anyway. Or breaks when the grammar changes.
[Prev in Thread] | Current Thread | [Next in Thread] |