Subject: bug#76373: 31.0.50; Extend autoconf-mode macro support

From: "Basil L. Contovounesios" <[email-masked]>
Date: Tue, 18 Feb 2025 20:16:40 +0100

Paul Eggert [2025-02-17 17:32 -0800] wrote:
> On 2025-02-17 13:05, Basil L. Contovounesios wrote:
>> The attached patch extends autoconf-mode
> Thanks, I installed it.

Thanks.

>> Also, a question: should defun-prompt-regexp really allow for leading
>> indentation?  In Autoconf scripts of the form:
>> if ...
>>    ...
>>    AC_MSG_...
>>    ...
>>    AC_MSG_...
>>    ...
>> fi
>> it means that beginning-of-defun stops at every indented AC_ or AM_
>> macro call (and with the attached patch, at any macro call with a known
>> namespace).
>
> Conversely, there may be conditional definitions of functions, e.g., Gnulib does
> this:
>
>   AC_DEFUN([gl_ASSERT_NO_GNULIB_TESTS],
>   [
>     dnl Override gl_MODULE_INDICATOR_FOR_TESTS.
>     AC_DEFUN([gl_MODULE_INDICATOR_FOR_TESTS], [])
>   ])

Right, but there seems to be some tension here between 'defun' as a
toplevel definition/form vs any (nested) definition.

> Could we change the search for defuns to be more selective? It's not reasonable
> to think that every AC_.... call is a defun.

Like so?

diff --git a/lisp/progmodes/autoconf.el b/lisp/progmodes/autoconf.el
index c5b076bfacc..c313aa8d671 100644
--- a/lisp/progmodes/autoconf.el
+++ b/lisp/progmodes/autoconf.el
@@ -54,6 +54,28 @@ autoconf--macro
         "gl") ;; Gnulib.
      ?_ autoconf--symbol))
 
+;; Autoconf macros that define a variable symbol.
+(rx-define autoconf--defvar
+  (| "AC_SUBST"
+     "AH_TEMPLATE"
+     "AH_VERBATIM"
+     "AM_CONDITIONAL"
+     "AM_MISSING_PROG"))
+
+;; Autoconf macros that define a function symbol.
+(rx-define autoconf--defun
+  (| "AC_DEFUN"
+     "AC_DEFUN_ONCE"
+     "AU_ALIAS"
+     "AU_DEFUN"))
+
+;; Autoconf macros that define something.
+(rx-define autoconf--define
+  (| "AC_DEFINE"
+     "AC_DEFINE_UNQUOTED"
+     autoconf--defvar
+     autoconf--defun))
+
 (defconst autoconf-definition-regexp
   ;; Historically this `defconst' defined only group #1.
   ;; For internal Font Lock use, the presence of an optional group #2
@@ -70,15 +92,8 @@ autoconf-definition-regexp
               ;; knowledge of shell syntax, so don't bother for now.
               (| (: plaindef (? (group-n 2 ?\()))
                  (: "_UNQUOTED" argbeg (group-n 1 (+ (not argend))))))
-           (: (| "AC_SUBST"
-                 "AH_TEMPLATE"
-                 "AH_VERBATIM"
-                 "AM_CONDITIONAL"
-                 "AM_MISSING_PROG"
-                 (group-n 2 (| "AC_DEFUN"
-                               "AC_DEFUN_ONCE"
-                               "AU_ALIAS"
-                               "AU_DEFUN")))
+           (: (| autoconf--defvar
+                 (group-n 2 autoconf--defun))
               plaindef))))
   "Matches Autoconf macro calls that define something.
 The thing being defined is captured in the first subexpression group.")
@@ -122,7 +137,7 @@ autoconf-mode
   "Major mode for editing Autoconf configure.ac files."
   (setq-local parens-require-spaces nil) ; for M4 arg lists
   ;; FIXME: Should indented macro calls really count as defuns?
-  (setq-local defun-prompt-regexp (rx bol (* (in "\t ")) autoconf--macro))
+  (setq-local defun-prompt-regexp (rx bol (* (in "\t ")) autoconf--define))
   (setq-local open-paren-in-column-0-is-defun-start nil)
   (setq-local comment-start "dnl ")
   ;; We want to avoid matching "dnl" in other text.

I'm on the fence about whether it's actually better like this.  I now
find it unpredictable just how far C-M-a will travel in search of a
definition, and Imenu already presents an alternative means of jumping
only to definitions.

But I don't feel too strongly and can see the utility either way, so I
defer to others who write more Autoconf than I do.

-- 
Basil