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

From: martin rudalics <[email-masked]>
Date: Sat, 19 Jun 2021 11:08:52 +0200

> Thanks.  But what I'd like to have is not a way of burying the Help
 > window, because I frequently need to consult it for quite some time.
 > What I'd like to have is a way of using its buttons without going to
 > that other window first.  For example, I'd love a command, bound to a
 > key globally, that would display the source of the function in the
 > same window as the Help window, then allow me to go back to the Help
 > window.

The attached is an attempt to do that.  Buggy and the nomenclature is
immature but I hope you get the idea.

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

+(defvar help-function-def-same-window nil)
+(defvar help-function-def-window nil)
+(defvar help-function-def-buffer nil)
+(defvar help-function-def-quit-restore nil)
+
+(defun help-forward-same-window ()
+  "Go to link following point of help window in that window."
+  (interactive)
+  (let* ((buffer (get-buffer "*Help*"))
+         (window (and buffer (get-buffer-window buffer))))
+    (if window
+        (with-selected-window window
+          (save-excursion
+            (let ((button (forward-button (point-min)))
+	          (help-function-def-same-window t))
+              (if button
+                  (progn
+                    (setq help-function-def-window window)
+                    (setq help-function-def-buffer buffer)
+                    (setq help-function-def-quit-restore
+                          (window-parameter window 'quit-restore))
+                    (button-activate button))
+                (message "No link found")))))
+      (message "No help window found"))))
+
+(defun help-backward-same-window ()
+  "Go back to help window."
+  (interactive)
+  (if (and (window-live-p help-function-def-window)
+           (buffer-live-p help-function-def-buffer))
+      (let ((buffer (window-buffer help-function-def-window)))
+        (set-window-buffer
+         help-function-def-window help-function-def-buffer)
+        (when help-function-def-quit-restore
+          ;; Pretend that window's buffer was never display in window.
+          (set-window-prev-buffers
+           help-function-def-window
+           (assq-delete-all
+            buffer (window-prev-buffers help-function-def-window)))
+          (set-window-parameter
+           help-function-def-window 'quit-restore
+           help-function-def-quit-restore))
+        (setq help-function-def-window nil)
+        (setq help-function-def-buffer nil)
+        (setq help-function-def-quit-restore nil))
+    (message "Cannot find help window or its buffer")))
+
+(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)
+      (message "No help window found"))))
+
+(define-key goto-map "f" 'help-forward-same-window)
+(define-key goto-map "b" 'help-backward-same-window)
+(define-key goto-map "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 +274,9 @@ 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-function-def-same-window
+          (pop-to-buffer-same-window (car location))
+        (pop-to-buffer (car location)))
       (run-hooks 'find-function-after-hook)
       (if position
           (progn