Subject: [PATCH] New hook 'help-setup-hook'
From: Eshel Yaron <[email-masked]>
To: [email-masked]
Date: Sat, 05 Oct 2024 09:14:54 +0200
List-Id: <debbugs-submit.debbugs.gnu.org>

Tags: patch

Add a new hook that allows commands that make use of bespoke variable
settings in the *Help* buffer to clean up after themselves.  This
generalizes and improves the accuracy of the hard-coded clean up that
help-setup-xref currently performs.

From e4d633d55370265f25cf229553ff16435b1c23b8 Mon Sep 17 00:00:00 2001
From: Eshel Yaron <[email-masked]>
Date: Sat, 5 Oct 2024 09:04:10 +0200
Subject: [PATCH] New hook 'help-setup-hook'

* lisp/help-mode.el (help-setup-hook): New hook.
(help-setup-xref): Run it.
* lisp/help.el (describe-bindings):
* lisp/help-fns.el (help-fns--setup-xref-backend): Use it
for clean up.
---
 lisp/help-fns.el  |  7 ++++++-
 lisp/help-mode.el | 25 +++++++++----------------
 lisp/help.el      | 15 ++++++++++++++-
 3 files changed, 29 insertions(+), 18 deletions(-)

diff --git a/lisp/help-fns.el b/lisp/help-fns.el
index 5cc8df6497f..c01529f410a 100644
--- a/lisp/help-fns.el
+++ b/lisp/help-fns.el
@@ -280,7 +280,12 @@ xref-backend-references
 
 (defun help-fns--setup-xref-backend ()
   (add-hook 'xref-backend-functions #'elisp--xref-backend nil t)
-  (setq-local semantic-symref-filepattern-alist '((help-mode "*.el"))))
+  (setq-local semantic-symref-filepattern-alist '((help-mode "*.el")))
+  (add-hook 'help-setup-hook
+            (lambda ()
+              (kill-local-variable 'xref-backend-functions)
+              (kill-local-variable 'semantic-symref-filepattern-alist))
+            nil t))
 
 ;;;###autoload
 (defun describe-function (function)
diff --git a/lisp/help-mode.el b/lisp/help-mode.el
index 7bb69a9389f..e14285269df 100644
--- a/lisp/help-mode.el
+++ b/lisp/help-mode.el
@@ -492,6 +492,13 @@ help-xref-url-regexp
   (purecopy "\\<[Uu][Rr][Ll][ \t\n]+['`‘]\\([^'’]+\\)['’]")
   "Regexp matching doc string references to a URL.")
 
+(defvar-local help-setup-hook nil
+  "Functions to call with no arguments when populating \"*Help*\" buffers.
+
+Emacs resets the buffer-local value of this variable after calling these
+functions, so that functions that you add to this hook buffer-locally
+are only called once, when another command reuses the \"*Help*\" buffer.")
+
 ;;;###autoload
 (defun help-setup-xref (item interactive-p)
   "Invoked from commands using the \"*Help*\" buffer to install some xref info.
@@ -505,22 +512,8 @@ help-setup-xref
 because we want to record the \"previous\" position of point so we can
 restore it properly when going back."
   (with-current-buffer (help-buffer)
-    ;; Disable `outline-minor-mode' in a reused Help buffer
-    ;; created by `describe-bindings' that enables this mode.
-    (when (bound-and-true-p outline-minor-mode)
-      (outline-minor-mode -1)
-      (mapc #'kill-local-variable
-            '(outline-search-function
-              outline-regexp
-              outline-heading-end-regexp
-              outline-level
-              outline-minor-mode-cycle
-              outline-minor-mode-highlight
-              outline-minor-mode-use-buttons
-              outline-default-state
-              outline-default-rules)))
-    (kill-local-variable 'xref-backend-functions)
-    (kill-local-variable 'semantic-symref-filepattern-alist)
+    (run-hooks 'help-setup-hook)
+    (kill-local-variable 'help-setup-hook)
     (when help-xref-stack-item
       (push (cons (point) help-xref-stack-item) help-xref-stack)
       (setq help-xref-forward-stack nil))
diff --git a/lisp/help.el b/lisp/help.el
index 5efe207c624..fd206480dcb 100644
--- a/lisp/help.el
+++ b/lisp/help.el
@@ -806,7 +806,20 @@ describe-bindings
               ;; Hide ^Ls.
               (while (search-forward "\n\f\n" nil t)
 		(put-text-property (1+ (match-beginning 0)) (1- (match-end 0))
-                                   'invisible t)))))))))
+                                   'invisible t))))
+          (add-hook 'help-setup-hook
+                    (lambda ()
+                      (outline-minor-mode -1)
+                      (mapc #'kill-local-variable
+                            '(outline-regexp
+                              outline-heading-end-regexp
+                              outline-level
+                              outline-minor-mode-cycle
+                              outline-minor-mode-highlight
+                              outline-minor-mode-use-buttons
+                              outline-default-state
+                              outline-default-rules)))
+                    nil t))))))
 
 (defun where-is (definition &optional insert)
   "Print message listing key sequences that invoke the command DEFINITION.
-- 
2.46.2