master 9307284c69e: Recognize non-alphanumeric characters in 'sh-script' defun names

Eli Zaretskii <[email protected]> Sat, 18 Jul 2026 05:09:18 -0400 (EDT)
Newsgroups gmane.emacs.diffs
Message-ID <[email protected]>
branch: master
commit 9307284c69e849895f6909c56f41cb0420d868b8
Author: Alan Mackenzie <[email protected]>
Commit: Eli Zaretskii <[email protected]>

    Recognize non-alphanumeric characters in 'sh-script' defun names
    
    Also amend the doc string of defun-prompt-regexp.  This fixes
    bug#81401.
    * lisp/progmodes/sh-script.el (sh-base-mode): Amend the value
    of 'defun-prompt-regexp' to use a "negative" rather than a
    "positive" list of characters.
    * lisp/emacs-lisp/lisp.el (defun-prompt-regexp).  Amend the doc
    string for clarity.
---
 lisp/emacs-lisp/lisp.el     |  7 +++++--
 lisp/progmodes/sh-script.el | 19 +++++++++++++------
 2 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/lisp/emacs-lisp/lisp.el b/lisp/emacs-lisp/lisp.el
index 1db2f5693b6..e0111af1a1d 100644
--- a/lisp/emacs-lisp/lisp.el
+++ b/lisp/emacs-lisp/lisp.el
@@ -31,8 +31,11 @@
 
 ;; Note that this variable is used by non-lisp modes too.
 (defcustom defun-prompt-regexp nil
-  "If non-nil, a regexp to ignore before a defun.
-This is only necessary if the opening paren or brace is not in column 0.
+  "If non-nil, matches a prefix on the line of a defun's opening paren.
+This regexp should begin with \"^\".  It is used to recognize a function's
+opening paren or brace when it is not in column 0.
+The prefix typically names the defun, and possibly gives its type and
+arguments.
 See function `beginning-of-defun'."
   :type '(choice (const nil)
 		 regexp)
diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el
index 4d025eeb18d..f9d4310f367 100644
--- a/lisp/progmodes/sh-script.el
+++ b/lisp/progmodes/sh-script.el
@@ -1492,12 +1492,19 @@ implementations.  Currently there are two: `sh-mode' and
   (setq-local skeleton-filter-function #'sh-feature)
   (setq-local skeleton-newline-indent-rigidly t)
   (setq-local defun-prompt-regexp
-              (concat
-               "^\\("
-               "\\(function[ \t]\\)?[ \t]*[[:alnum:]_]+[ \t]*([ \t]*)"
-               "\\|"
-               "function[ \t]+[[:alnum:]_]+[ \t]*\\(([ \t]*)\\)?"
-               "\\)[ \t]*"))
+              (let* ((fname-char "^ \t\n\r\v\f\\\"'`$|&;()<>")
+                     (fname-char0 (concat fname-char "#"))
+                     (fname-re
+                      (concat "[" fname-char0 "]"
+                              "[" fname-char "]*")))
+                (concat
+                 "^\\([ \t]*"
+                 "\\("
+                 "\\(function[ \t]+\\)?" fname-re "[ \t]*([ \t]*)"
+                 "\\|"
+                 "function[ \t]+" fname-re "[ \t]*\\(([ \t]*)\\)?"
+                 "\\)"
+                 "\\)[ \t]*")))
   (setq-local add-log-current-defun-function #'sh-current-defun-name)
   (add-hook 'completion-at-point-functions
             #'sh-completion-at-point-function nil t)