all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Randy Taylor <dev@rjt.dev>
To: Juan Palacios <jpalaciosdev@gmail.com>
Cc: 66845@debbugs.gnu.org, Yuan Fu <casouri@gmail.com>
Subject: bug#66845: 29.1; cmake-ts-mode indentation broken
Date: Wed, 01 Nov 2023 02:45:26 +0000	[thread overview]
Message-ID: <4m1KSu7eJ_B7nNCVOnvZM_edTrQhMTtxiKFwUB4zNoYufrWuTYcq_tL1iIRml2xqDRdTDavJBnE7B4iNmswVLwzGXI96E_FNcXkCeDqUzVo=@rjt.dev> (raw)
In-Reply-To: <CAEPLNsfw8rC-cLOptvHiNh_XtpOZ_e15cUeFtv_hb2PEpn-wpA@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 2627 bytes --]

On Tuesday, October 31st, 2023 at 07:35, Juan Palacios <jpalaciosdev@gmail.com> wrote:
> Using cmake grammar from https://github.com/uyha/tree-sitter-cmake
> 
> Reproduction:
> 1. emacs -q
> 2. C-x C-f test.cmake
> 3. M-x cmake-ts-mode
> 4. Insert the following text:
> if(TRUE)
> message("indent")
> endif()
> 5. Move the point to the beginning of the second line.
> 6. TAB
> 7. Notice that no indentation is performed.
> 
> treesit-simple-indent-rules local value:
> ((cmake
> ((node-is ")")
> parent-bol 0)
> ((node-is "else_command")
> parent-bol 0)
> ((node-is "elseif_command")
> parent-bol 0)
> ((node-is "endforeach_command")
> parent-bol 0)
> ((node-is "endfunction_command")
> parent-bol 0)
> ((node-is "endif_command")
> parent-bol 0)
> ((parent-is "foreach_loop")
> parent-bol cmake-ts-mode-indent-offset)
> ((parent-is "function_def")
> parent-bol cmake-ts-mode-indent-offset)
> ((parent-is "if_condition")
> parent-bol cmake-ts-mode-indent-offset)
> ((parent-is "normal_command")
> parent-bol cmake-ts-mode-indent-offset)))
> 
> treesit-explore-mode shows:
> (if_condition
> (if_command (if) (
> (argument_list
> (argument (unquoted_argument)))
> ))
> (body
> (normal_command (identifier) (
> (argument_list
> (argument
> (quoted_argument " (quoted_element) ")))
> )))
> (endif_command (endif) ( )))
> 

I've attached a patch fixing this while retaining compatibility with
older grammars. 2 new versions of the grammar, v0.3.0 and v0.4.0
(and anything beyond for now) wrap things in new nodes.

Yuan,
It's been awhile since I've touched any tree-sitter stuff so I'm
probably missing something obvious, but it seems to me like the
function I've added in the patch
(cmake-ts-mode--argument-list-body-offset) is working around a bug
somewhere? I'm not sure why the start of line_comment is considered
parent-bol for indentation.

For example, with this test cmake file: (test.cmake)
if(TRUE)
  # Comment.
  message("indent")
endif()

We get:
(source_file
 (if_condition
  (if_command (if) (
   (argument_list
    (argument (unquoted_argument)))
   ))
  (body (line_comment)
   (normal_command (identifier) (
    (argument_list
     (argument
      (quoted_argument " (quoted_element) ")))
    )))
  (endif_command (endif) ( ))))

With cmake-ts-mode--argument-list-body-offset always returning
cmake-ts-mode-indent-offset (which is what I would expect), the
`parent-is "body"` rule will cause this indentation:
if(TRUE)
  # Comment.
    message("indent")
endif()

Am I being silly or is there indeed something odd going on?

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Fix-cmake-ts-mode-indentation-Bug-66845.patch --]
[-- Type: text/x-patch; name=0001-Fix-cmake-ts-mode-indentation-Bug-66845.patch, Size: 3053 bytes --]

From 544396b7afa55c4d12fc6f03198199017582b8df Mon Sep 17 00:00:00 2001
From: Randy Taylor <dev@rjt.dev>
Date: Tue, 31 Oct 2023 22:08:25 -0400
Subject: [PATCH] Fix cmake-ts-mode indentation (Bug#66845)

* lisp/progmodes/cmake-ts-mode.el
(cmake-ts-mode--argument-list-body-offset): New function.
(cmake-ts-mode--indent-rules): Support versions v0.3.0 and v0.4.0 of
the grammar.
(cmake-ts-mode--font-lock-compatibility-fe9b5e0): Fix docstring.
---
 lisp/progmodes/cmake-ts-mode.el | 30 ++++++++++++++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)

diff --git a/lisp/progmodes/cmake-ts-mode.el b/lisp/progmodes/cmake-ts-mode.el
index 53d471c381a..d2d66a461f3 100644
--- a/lisp/progmodes/cmake-ts-mode.el
+++ b/lisp/progmodes/cmake-ts-mode.el
@@ -52,6 +52,24 @@ cmake-ts-mode--syntax-table
     table)
   "Syntax table for `cmake-ts-mode'.")
 
+(defun cmake-ts-mode--argument-list-body-offset (_n parent &rest _)
+  "This offset is used for argument_list and body nodes.
+
+For some reason, a comment after an argument_list or body node causes
+the next line to indent as if the comment was the parent. For example:
+
+1 if (TRUE)
+2   # Comment.
+3     func()
+4 endif()
+
+Line 3 is indented as if the comment (line 2) was parent-bol,
+when line 1 should be parent-bol."
+  (when-let (node (treesit-node-child parent 0 t))
+    (if (string-equal "line_comment" (treesit-node-type node))
+        0
+      cmake-ts-mode-indent-offset)))
+
 (defvar cmake-ts-mode--indent-rules
   `((cmake
      ((node-is ")") parent-bol 0)
@@ -60,6 +78,14 @@ cmake-ts-mode--indent-rules
      ((node-is "endforeach_command") parent-bol 0)
      ((node-is "endfunction_command") parent-bol 0)
      ((node-is "endif_command") parent-bol 0)
+     ;;; Release v0.4.0 wraps arguments in an argument_list node.
+     ,@(ignore-errors
+         (treesit-query-capture 'cmake '((argument_list) @capture))
+         `(((parent-is "argument_list") parent-bol cmake-ts-mode--argument-list-body-offset)))
+     ;;; Release v0.3.0 wraps the body of commands into a body node.
+     ,@(ignore-errors
+         (treesit-query-capture 'cmake '((body) @capture))
+         `(((parent-is "body") parent-bol cmake-ts-mode--argument-list-body-offset)))
      ((parent-is "foreach_loop") parent-bol cmake-ts-mode-indent-offset)
      ((parent-is "function_def") parent-bol cmake-ts-mode-indent-offset)
      ((parent-is "if_condition") parent-bol cmake-ts-mode-indent-offset)
@@ -89,8 +115,8 @@ cmake-ts-mode--if-conditions
   "CMake if conditions for tree-sitter font-locking.")
 
 (defun cmake-ts-mode--font-lock-compatibility-fe9b5e0 ()
-  "Indent rules helper, to handle different releases of tree-sitter-cmake.
-Check if a node type is available, then return the right indent rules."
+  "Font lock helper, to handle different releases of tree-sitter-cmake.
+Check if a node type is available, then return the right font lock rules."
   ;; handle commit fe9b5e0
   (condition-case nil
       (progn (treesit-query-capture 'cmake '((argument_list) @capture))
-- 
2.42.0


  parent reply	other threads:[~2023-11-01  2:45 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-10-31 11:35 bug#66845: 29.1; cmake-ts-mode indentation broken Juan Palacios
2023-10-31 15:50 ` Randy Taylor
2023-11-01  2:45 ` Randy Taylor [this message]
2023-11-05 14:32   ` Juan Palacios
2023-11-05 18:16     ` Fu Yuan
2023-11-07  8:25   ` Yuan Fu
2023-11-07 17:21     ` Randy Taylor
2023-11-07 20:11       ` Juan Palacios
2023-11-08  2:52       ` Yuan Fu
2023-11-08  3:42         ` Randy Taylor
2023-11-08 12:33           ` Eli Zaretskii

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='4m1KSu7eJ_B7nNCVOnvZM_edTrQhMTtxiKFwUB4zNoYufrWuTYcq_tL1iIRml2xqDRdTDavJBnE7B4iNmswVLwzGXI96E_FNcXkCeDqUzVo=@rjt.dev' \
    --to=dev@rjt.dev \
    --cc=66845@debbugs.gnu.org \
    --cc=casouri@gmail.com \
    --cc=jpalaciosdev@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.