Subject: bug#73872: 30.0.91; emacs-lisp-mode-syntax-table active when calling `describe-variable' on variable with textually large value.

From: Stefan Monnier <[email-masked]>
Date: Sat, 21 Dec 2024 10:10:11 -0500

>> Aahhhh!
>> So the underlying problem already bite in the usual case but you worked
>> around it by changing `help-mode-syntax-table`.
>> I think your change to `help-mode-syntax-table` is about right, so we
>> should include it in any fix to this bug.
> I was going to install that change, but then I noticed that it removed
> the call to terpri.  Is that intentional?

[ I don't think the `terpri` was meant to be removed, no.  ]

Here's the patch I suggest we install (obviously not on `emacs-30`).

        Stefan

2024-12-21  Stefan Monnier  <[email-masked]>

    * lisp/help-mode.el (help-mode-syntax-table): Mark `;` as punctuation.
    (help-make-xrefs): Use `with-syntax-table`.

    * lisp/help-fns.el (describe-variable): Don't change the buffer's
    syntax-table when moving the var's value to the end (bug#73872).
    Put a `syntax-table` property on the var's value so sexp navigation
    does not depend on the help-mode-syntax-table.

diff --git a/lisp/help-fns.el b/lisp/help-fns.el
index c87c86bae84..ae6b77e7849 100644
--- a/lisp/help-fns.el
+++ b/lisp/help-fns.el
@@ -1437,21 +1437,29 @@ describe-variable
 			     (format-message "`%s'" rep)
 			   rep)))
                       (start (point)))
-		  (if (< (+ (length print-rep) (point) (- line-beg)) 68)
-		      (insert " " print-rep)
-		    (terpri)
-                    (let ((buf (current-buffer)))
-                      (with-temp-buffer
-                        (lisp-data-mode)
-                        (set-syntax-table emacs-lisp-mode-syntax-table)
-                        (insert print-rep)
-                        (pp-buffer)
-                        (font-lock-ensure)
-                        (let ((pp-buffer (current-buffer)))
-                          (with-current-buffer buf
-                            (insert-buffer-substring pp-buffer)))))
-                    ;; Remove trailing newline.
-                    (and (= (char-before) ?\n) (delete-char -1)))
+		 (let (beg)
+		   (if (< (+ (length print-rep) (point) (- line-beg)) 68)
+		       (progn
+		         (setq beg (1+ (point)))
+		         (insert " " print-rep))
+		     (terpri)
+                     (setq beg (point))
+                     (let ((buf (current-buffer)))
+                       (with-temp-buffer
+                         (lisp-data-mode)
+                         (insert print-rep)
+                         (pp-buffer)
+                         (font-lock-ensure)
+                         (let ((pp-buffer (current-buffer)))
+                           (with-current-buffer buf
+                             (insert-buffer-substring pp-buffer))))))
+                   ;; Remove trailing newline.
+                   (and (= (char-before) ?\n) (delete-char -1))
+                   ;; Put a `syntax-table' property on the data, as
+                   ;; a kind of poor man's multi-major-mode support here.
+                   (put-text-property beg (point)
+		                      'syntax-table
+		                      lisp-data-mode-syntax-table))
                   (help-fns--editable-variable start (point)
                                                variable val buffer)
 		  (let* ((sv (get variable 'standard-value))
@@ -1515,10 +1523,6 @@ describe-variable
 	    ;; If the value is large, move it to the end.
 	    (with-current-buffer standard-output
 	      (when (> (count-lines (point-min) (point-max)) 10)
-		;; Note that setting the syntax table like below
-		;; makes forward-sexp move over a `'s' at the end
-		;; of a symbol.
-		(set-syntax-table emacs-lisp-mode-syntax-table)
 		(goto-char val-start-pos)
 		(when (looking-at "value is") (replace-match ""))
 		(save-excursion
diff --git a/lisp/help-mode.el b/lisp/help-mode.el
index 33b8eccab2c..aa705bf56d1 100644
--- a/lisp/help-mode.el
+++ b/lisp/help-mode.el
@@ -143,6 +143,8 @@ help-mode-syntax-table
     ;; break when a quoted string contains punctuation.
     (modify-syntax-entry ?‘ "(’  " table)
     (modify-syntax-entry ?’ ")‘  " table)
+    ;; `;' doesn't start a comment (bug#73872).
+    (modify-syntax-entry ?\; "." table)
     table)
   "Syntax table used in `help-mode'.")
 
@@ -587,13 +587,10 @@
       ;; Skip the first bit, which has already been buttonized.
       (forward-paragraph)
       (let ((old-modified (buffer-modified-p)))
-        (let ((stab (syntax-table))
-              (case-fold-search t)
+        (let ((case-fold-search t)
               (inhibit-read-only t))
-          (set-syntax-table help-mode-syntax-table)
+          (with-syntax-table help-mode-syntax-table
           ;; The following should probably be abstracted out.
-          (unwind-protect
-              (progn
                 ;; Info references
                 (save-excursion
                   (while (re-search-forward help-xref-info-regexp nil t)
@@ -679,7 +676,6 @@
                     (let ((sym (intern-soft (match-string 1))))
                       (if (fboundp sym)
                           (help-xref-button 1 'help-function sym))))))
-            (set-syntax-table stab))
           ;; Delete extraneous newlines at the end of the docstring
           (goto-char (point-max))
           (while (and (not (bobp)) (bolp))