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.