summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lisp/progmodes/c-ts-mode.el30
-rw-r--r--test/lisp/progmodes/c-ts-mode-resources/indent-preproc.erts45
-rw-r--r--test/lisp/progmodes/c-ts-mode-tests.el4
3 files changed, 74 insertions, 5 deletions
diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el
index 05875e9267a..76c80d9a068 100644
--- a/lisp/progmodes/c-ts-mode.el
+++ b/lisp/progmodes/c-ts-mode.el
@@ -233,6 +233,25 @@ delimiters < and >'s."
;;; Indent
+(defun c-ts-mode--preproc-offset (_n _p &rest _)
+ "This anchor is used for preprocessor directives.
+
+Because node is nil at the moment of indentation, we use
+`treesit-node-on' to capture the anonymous node covering the
+newline. If the grand-parent of that node is the
+translation_unit itself, we don't indent. Otherwise, just indent
+one step according to the great-grand-parent indent level. The
+reason there is a difference between grand-parent and
+great-grand-parent here is that the node containing the newline
+is actually the parent of point at the moment of indentation."
+ (when-let ((node (treesit-node-on (point) (point))))
+ (if (string-equal "translation_unit"
+ (treesit-node-type
+ (treesit-node-parent
+ (treesit-node-parent node))))
+ 0
+ c-ts-mode-indent-offset)))
+
(defun c-ts-mode--indent-styles (mode)
"Indent rules supported by `c-ts-mode'.
MODE is either `c' or `cpp'."
@@ -265,13 +284,14 @@ MODE is either `c' or `cpp'."
((match nil "do_statement" "body") parent-bol c-ts-mode-indent-offset)
((match nil "for_statement" "body") parent-bol c-ts-mode-indent-offset)
- ((match "preproc_ifdef" "compound_statement") point-min 0)
- ((match "#endif" "preproc_ifdef") point-min 0)
- ((match "preproc_if" "compound_statement") point-min 0)
- ((match "#endif" "preproc_if") point-min 0)
- ((match "preproc_function_def" "compound_statement") point-min 0)
+ ((node-is "preproc") point-min 0)
+ ((node-is "#endif") point-min 0)
((match "preproc_call" "compound_statement") point-min 0)
+ ((n-p-gp nil "preproc" "translation_unit") point-min 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)
+
((parent-is "function_definition") parent-bol 0)
((parent-is "conditional_expression") first-sibling 0)
((parent-is "assignment_expression") parent-bol c-ts-mode-indent-offset)
diff --git a/test/lisp/progmodes/c-ts-mode-resources/indent-preproc.erts b/test/lisp/progmodes/c-ts-mode-resources/indent-preproc.erts
new file mode 100644
index 00000000000..5a4996f642e
--- /dev/null
+++ b/test/lisp/progmodes/c-ts-mode-resources/indent-preproc.erts
@@ -0,0 +1,45 @@
+Code:
+ (lambda ()
+ (c-ts-mode)
+ (newline)
+ (indent-for-tab-command))
+
+Point-Char: |
+
+Name: Indents inside #if preproc
+
+=-=
+static void
+free_glyph_pool (struct glyph_pool *pool)
+{
+ if (pool)
+ {
+#if defined GLYPH_DEBUG|
+#endif
+ }
+}
+=-=
+static void
+free_glyph_pool (struct glyph_pool *pool)
+{
+ if (pool)
+ {
+#if defined GLYPH_DEBUG
+ |
+#endif
+ }
+}
+=-=-=
+
+Name: Indents to 0 if #if preproc at root
+
+=-=
+#if 0|
+/* */
+static void
+=-=
+#if 0
+|
+/* */
+static void
+=-=-=
diff --git a/test/lisp/progmodes/c-ts-mode-tests.el b/test/lisp/progmodes/c-ts-mode-tests.el
index ddf64b40736..ea5fab4cbef 100644
--- a/test/lisp/progmodes/c-ts-mode-tests.el
+++ b/test/lisp/progmodes/c-ts-mode-tests.el
@@ -27,6 +27,10 @@
(skip-unless (treesit-ready-p 'c))
(ert-test-erts-file (ert-resource-file "indent.erts")))
+(ert-deftest c-ts-mode-test-indentation-preproc ()
+ (skip-unless (treesit-ready-p 'c))
+ (ert-test-erts-file (ert-resource-file "indent-preproc.erts")))
+
(ert-deftest c-ts-mode-test-indentation-bsd ()
(skip-unless (treesit-ready-p 'c))
(ert-test-erts-file (ert-resource-file "indent-bsd.erts")))