Subject: Re: bug#36767: 26.1; request: add more quick keys to the *Help* buffer

From: martin rudalics <[email-masked]>
Date: Sun, 20 Jun 2021 11:21:51 +0200

> Thanks, looks like a good start.

Attached find a slightly simpler and hopefully more correct version.

martin
--- a/lisp/help-mode.el
+++ b/lisp/help-mode.el
@@ -200,6 +200,64 @@ 'help-customize-face
 		   (customize-face v))
   'help-echo (purecopy "mouse-2, RET: customize face"))

+(defvar help-link-follow nil
+  "Information stored by `help-link-follow'.
+If this is non-nil, `help-function-def--button-function' will try to
+display its location in the \"same\" window.")
+
+(defun help-link-follow ()
+  "Follow or return from first link in help window.
+If this function finds a help window, it will try to display in
+that window the buffer referred to by the first link found in its
+help buffer.  If there is no help window, this function will try
+to restore the help window from an earlier followed link."
+  (interactive)
+  (cond
+   ((let* ((buffer (get-buffer "*Help*"))
+           (window (and buffer (get-buffer-window buffer))))
+      (and window
+           (with-selected-window window
+             (save-excursion
+               (let ((button (forward-button (point-min)))
+                     (par (window-parameter window 'quit-restore)))
+                 (if button
+                     (condition-case nil
+                         (progn
+                           (setq help-link-follow (list buffer window par))
+                           (button-activate button))
+                       (error (setq help-link-follow nil)))
+                   (user-error "No link found"))))))))
+   ((and help-link-follow
+         (buffer-live-p (nth 0 help-link-follow))
+         (window-live-p (nth 1 help-link-follow)))
+    (let* ((window (nth 1 help-link-follow))
+           (buffer (window-buffer window)))
+      (set-window-buffer window (nth 0 help-link-follow))
+      (when (nth 2 help-link-follow)
+        ;; Pretend that the window's buffer was never displayed in this
+        ;; window to avoid that quitting the help window restores that
+        ;; buffer in the help window.
+        (set-window-prev-buffers
+         window (assq-delete-all buffer (window-prev-buffers window)))
+        (set-window-parameter
+         window 'quit-restore (nth 2 help-link-follow)))
+      (setq help-link-follow nil)))
+   (t
+    (setq help-link-follow nil)
+    (user-error "No help link found"))))
+
+(defun help-window-quit ()
+  "Quit any help window found."
+  (interactive)
+  (let* ((buffer (get-buffer "*Help*"))
+         (window (and buffer (get-buffer-window buffer))))
+    (if window
+        (quit-restore-window window)
+      (user-error "No help window found"))))
+
+(define-key help-map "\C-l" 'help-link-follow)
+(define-key help-map "\C-q" 'help-window-quit)
+
 (defun help-function-def--button-function (fun &optional file type)
   (or file
       (setq file (find-lisp-object-file-name fun type)))
@@ -214,7 +272,10 @@ help-function-def--button-function
     (let* ((location
             (find-function-search-for-symbol fun type file))
            (position (cdr location)))
-      (pop-to-buffer (car location))
+      (if help-link-follow
+          (display-buffer
+           (car location) display-buffer--same-window-action)
+        (pop-to-buffer (car location)))
       (run-hooks 'find-function-after-hook)
       (if position
           (progn