]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix c-ts-mode preproc directive indentation
authorYuan Fu <casouri@gmail.com>
Sat, 4 Mar 2023 22:39:44 +0000 (14:39 -0800)
committerYuan Fu <casouri@gmail.com>
Sat, 4 Mar 2023 23:03:12 +0000 (15:03 -0800)
Mentioned in bug#61893, although not the subject of that report.  This
change fixes indentation for nested directives.  For example, when the
directive involves elif and the like, the elif is nested in the if
directive, so simply using grand-parent and great-grand-parent for
anchor is insufficient, because the nesting can grow arbitrarily.

The test added also covers the last preproc fix.

* lisp/progmodes/c-ts-mode.el:
(c-ts-mode--standalone-parent-skip-preproc): New function.
(c-ts-mode--indent-styles): New rules.
* test/lisp/progmodes/c-ts-mode-resources/indent-preproc.erts: New test.

lisp/progmodes/c-ts-mode.el
test/lisp/progmodes/c-ts-mode-resources/indent-preproc.erts

index 05c471e6fb48c873cb4a2062d0691fb53de241f9..f40bbc57eb5032c0ff4bb26c3320ebdb52d8d722 100644 (file)
@@ -299,6 +299,23 @@ PARENT and BOL are like other anchor functions."
     ;; prev-sibling doesn't have a child.
     (treesit-node-start prev-sibling)))
 
+(defun c-ts-mode--standalone-parent-skip-preproc (_n parent &rest _)
+  "Like the standalone-parent anchor but skips preproc nodes.
+PARENT is the same as other anchor functions."
+  (save-excursion
+    (treesit-node-start
+     (treesit-parent-until
+      ;; Use PARENT rather than NODE, to handle the case where NODE is
+      ;; nil.
+      parent (lambda (node)
+               (and node
+                    (not (string-match "preproc" (treesit-node-type node)))
+                    (progn
+                      (goto-char (treesit-node-start node))
+                      (looking-back (rx bol (* whitespace))
+                                    (line-beginning-position)))))
+      t))))
+
 (defun c-ts-mode--standalone-grandparent (_node parent bol &rest args)
   "Like the standalone-parent anchor but pass it the grandparent.
 PARENT, BOL, ARGS are the same as other anchor functions."
@@ -330,13 +347,28 @@ MODE is either `c' or `cpp'."
            ((parent-is "labeled_statement")
             c-ts-mode--standalone-grandparent c-ts-mode-indent-offset)
 
+           ;; Preproc directives
            ((node-is "preproc") column-0 0)
            ((node-is "#endif") column-0 0)
            ((match "preproc_call" "compound_statement") column-0 0)
 
+           ;; Top-level things under a preproc directive.  Note that
+           ;; "preproc" matches more than one type: it matches
+           ;; preproc_if, preproc_elif, etc.
            ((n-p-gp nil "preproc" "translation_unit") column-0 0)
-           ((n-p-gp nil "\n" "preproc") great-grand-parent c-ts-mode--preproc-offset)
-           ((parent-is "preproc") grand-parent c-ts-mode-indent-offset)
+           ;; Indent rule for an empty line after a preproc directive.
+           ((and no-node (parent-is ,(rx (or "\n" "preproc"))))
+            c-ts-mode--standalone-parent-skip-preproc c-ts-mode--preproc-offset)
+           ;; Statement under a preproc directive, the first statement
+           ;; indents against parent, the rest statements indent to
+           ;; their prev-sibling.
+           ((match nil ,(rx "preproc_" (or "if" "elif")) nil 3 3)
+            c-ts-mode--standalone-parent-skip-preproc c-ts-mode-indent-offset)
+           ((match nil "preproc_ifdef" nil 2 2)
+            c-ts-mode--standalone-parent-skip-preproc c-ts-mode-indent-offset)
+           ((match nil "preproc_else" nil 1 1)
+            c-ts-mode--standalone-parent-skip-preproc c-ts-mode-indent-offset)
+           ((parent-is "preproc") c-ts-mode--anchor-prev-sibling 0)
 
            ((parent-is "function_definition") parent-bol 0)
            ((parent-is "conditional_expression") first-sibling 0)
index 57610b5483eec9336a48121cb77f0a09d63fdb45..0f9256ad9841973ecae034cea72af86e2e37cc19 100644 (file)
@@ -44,3 +44,37 @@ static void
 /* */
 static void
 =-=-=
+
+Code:
+  (lambda ()
+    (c-ts-mode)
+    (setq-local indent-tabs-mode nil)
+    (setq-local c-ts-mode-indent-offset 2)
+    (c-ts-mode-set-style 'gnu)
+    (indent-region (point-min) (point-max)))
+
+Name: Prev-Sibling When Prev-Sibling is Preproc
+
+=-=
+static void
+free_glyph_pool (struct glyph_pool *pool)
+{
+  if (pool)
+    {
+#if defined GLYPH_DEBUG
+      int c = 1;
+#endif
+      int check_this = 3;
+
+#ifdef stuff
+      int c = 1;
+#elif defined stuff
+      int e = 5;
+#else
+      int d = 11;
+      int f = 11;
+#endif
+      int check_this = 3;
+    }
+}
+=-=-=