Subject: Re: bug#76693: [PATCH] Use TS to support 'hs-minor-mode' in 'lua-ts-mode'

From: john muhl <[email-masked]>
Date: Fri, 07 Mar 2025 08:29:55 -0600

Updated patch with Juri’s feedback.

>From 5f4d527a4a53a0fe7b46dc25a64f2bd3bc7337ce Mon Sep 17 00:00:00 2001
From: john muhl <[email-masked]>
Date: Wed, 26 Feb 2025 10:31:24 -0600
Subject: [PATCH] Use TS to support 'hs-minor-mode' in 'lua-ts-mode'

* lisp/progmodes/lua-ts-mode.el (lua-ts-mode): Add list type to
'treesit-thing-settings'.
* lisp/progmodes/hideshow.el (hs-special-modes-alist):
Remove regular expression based implementation.
* test/lisp/progmodes/lua-ts-mode-resources/hide-show.lua: New file.
* test/lisp/progmodes/lua-ts-mode-tests.el (lua-ts-test-hideshow):
Add test.  (Bug#76693)
---
 lisp/progmodes/hideshow.el                    |  1 -
 lisp/progmodes/lua-ts-mode.el                 | 46 +++++++++++--------
 .../lua-ts-mode-resources/hide-show.lua       | 43 +++++++++++++++++
 test/lisp/progmodes/lua-ts-mode-tests.el      | 13 ++++++
 4 files changed, 83 insertions(+), 20 deletions(-)
 create mode 100644 test/lisp/progmodes/lua-ts-mode-resources/hide-show.lua

diff --git a/lisp/progmodes/hideshow.el b/lisp/progmodes/hideshow.el
index c9b43fe8e16..c1d62fb92ab 100644
--- a/lisp/progmodes/hideshow.el
+++ b/lisp/progmodes/hideshow.el
@@ -266,7 +266,6 @@ hs-special-modes-alist
     (java-ts-mode "{" "}" "/[*/]" nil nil)
     (js-mode "{" "}" "/[*/]" nil)
     (js-ts-mode "{" "}" "/[*/]" nil)
-    (lua-ts-mode "{\\|\\[\\[" "}\\|\\]\\]" "--" nil)
     (mhtml-mode "{\\|<[^/>]*?" "}\\|</[^/>]*[^/]>" "<!--" mhtml-forward nil)
     ;; Add more support here.
     )
diff --git a/lisp/progmodes/lua-ts-mode.el b/lisp/progmodes/lua-ts-mode.el
index de93d0fdaba..b4025c23649 100644
--- a/lisp/progmodes/lua-ts-mode.el
+++ b/lisp/progmodes/lua-ts-mode.el
@@ -791,31 +791,39 @@ lua-ts-mode
                 (rx (or "function_declaration" "function_definition")))
     (setq-local treesit-thing-settings
                 `((lua
-                   (function ,(rx (or "function_declaration"
-                                      "function_definition")))
+                   (function (or "function_declaration"
+                                 "function_definition"))
                    (keyword ,(regexp-opt lua-ts--keywords 'symbols))
-                   (loop-statement ,(rx (or "do_statement"
-                                            "for_statement"
-                                            "repeat_statement"
-                                            "while_statement")))
+                   (loop-statement (or "do_statement"
+                                       "for_statement"
+                                       "repeat_statement"
+                                       "while_statement"))
                    (sentence (or function
                                  loop-statement
-                                 ,(rx (or "assignment_statement"
-                                          "comment"
-                                          "field"
-                                          "function_call"
-                                          "if_statement"
-                                          "return_statement"
-                                          "variable_declaration"))))
+                                 comment
+                                 "assignment_statement"
+                                 "field"
+                                 "function_call"
+                                 "if_statement"
+                                 "return_statement"
+                                 "variable_declaration"))
                    (sexp (or function
                              keyword
                              loop-statement
-                             ,(rx (or "arguments"
-                                      "parameters"
-                                      "parenthesized_expression"
-                                      "string"
-                                      "table_constructor"))))
-                   (text "comment"))))
+                             "arguments"
+                             "parameters"
+                             "parenthesized_expression"
+                             "string"
+                             "table_constructor"))
+                   (list (or function
+                             loop-statement
+                             "arguments"
+                             "parameters"
+                             "table_constructor"
+                             "parenthesized_expression"
+                             ,(rx bos "if_statement" eos)))
+                   (text (or comment "string"))
+                   (comment ,(rx bos "comment" eos)))))
 
     ;; Imenu/Outline/Which-function.
     (setq-local treesit-simple-imenu-settings
diff --git a/test/lisp/progmodes/lua-ts-mode-resources/hide-show.lua b/test/lisp/progmodes/lua-ts-mode-resources/hide-show.lua
new file mode 100644
index 00000000000..a4831eba273
--- /dev/null
+++ b/test/lisp/progmodes/lua-ts-mode-resources/hide-show.lua
@@ -0,0 +1,43 @@
+--[[
+This is a
+comment block.
+]]
+local function fun ()
+    print("fun")
+end
+local f = (function ()
+    print(1)
+end)
+for i = 1, 10 do
+  print(i)
+end
+repeat
+    print("repeat")
+until false
+while true do
+    print("while")
+end
+do
+    print(1)
+end
+local t = {
+    a=1,
+    b=2,
+}
+if true then
+    print(1)
+elseif false then
+    print(0)
+else
+    print(0)
+end
+function f1 (has,
+             lots,
+             of,
+             parameters)
+    print("ok")
+end
+print(1,
+      2,
+      3,
+      4)
diff --git a/test/lisp/progmodes/lua-ts-mode-tests.el b/test/lisp/progmodes/lua-ts-mode-tests.el
index 44c31648586..b14e9518451 100644
--- a/test/lisp/progmodes/lua-ts-mode-tests.el
+++ b/test/lisp/progmodes/lua-ts-mode-tests.el
@@ -22,6 +22,7 @@
 (require 'ert)
 (require 'ert-font-lock)
 (require 'ert-x)
+(require 'hideshow)
 (require 'treesit)
 (require 'which-func)
 
@@ -48,6 +49,18 @@ lua-ts-test-which-function
     (should (equal "f" (which-function)))
     (which-function-mode -1)))
 
+(ert-deftest lua-ts-test-hideshow ()
+  (skip-unless (treesit-ready-p 'lua t))
+  (with-temp-buffer
+    (insert-file-contents (ert-resource-file "hide-show.lua"))
+    (lua-ts-mode)
+    (hs-minor-mode)
+    (hs-hide-all)
+    (should (= 11 (length (overlays-in (point-min) (point-max)))))
+    (hs-show-all)
+    (should (= 0 (length (overlays-in (point-min) (point-max)))))
+    (hs-minor-mode -1)))
+
 (provide 'lua-ts-mode-tests)
 
 ;;; lua-ts-mode-tests.el ends here
-- 
2.48.1

john muhl <[email-masked]> writes:

> Juri Linkov <[email-masked]> writes:
>
>>>> This changes the hs-minor-mode suppport to use tree-sitter list
>>>> things instead of regexps.
>>>
>>> * lisp/progmodes/lua-ts-mode.el (lua-ts-mode): Add list type to
>>> 'treesit-thing-settings'.
>>
>> Coincidentally this is what I'm currently doing for all ts-modes
>> according to the principles agreed in bug#73404.
>>
>> And it's nice to see that your changes are aligned with them.
>
> That’s good to hear.
>
>> There is no need to follow these principles since only you
>> as the author of the ts-mode decide what is suitable for this ts-mode.
>>
>> But it would just make it easier for programmers in different languages
>> to switch between ts-modes that will meet their expectations.
>>
>> I noticed only a few things that look like omission:
>>
>> 1. "arguments" and "parameters" are parenthesized expressions,
>>    but are missing in the 'list' setting;
>>
>> 2. "if_statement" without the anchors "\\`...\\'" (bos/eos in rx)
>>    matches "elseif_statement" too.  But unlike "if_statement",
>>    "elseif_statement" doesn't end with the "end" keyword
>>    (whereas "else_statement" doesn't end with "end" too
>>     but correctly excluded from matching);
>>
>> 3. Also would be nice to support '(forward-comment 1)'
>>    with something like (comment ,(rx bos "comment" eos))
>
> Sounds good. I was aiming for parity with lua-mode but no reason
> to stop there. I’ll get an updated patch over soon.
>
> Thanks for the help.