From 97badaab7969ed5a306d6bcd320eb3d592a7f4ae Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Mon, 2 May 2022 11:30:43 +0200 Subject: [PATCH] Allow reusing the *Help* window with `i'/`s/ commands * doc/emacs/help.texi (Help): Document it. * lisp/help-mode.el (help-function-def--button-function): Use it. * lisp/help-mode.el (help-goto-info): Use it. * lisp/help.el (help-window-select): Mention it. (help-window-keep-selected): New user option (bug#9054). * lisp/info-look.el (info-lookup-symbol): (info-lookup): Allow keeping the same window. --- doc/emacs/help.texi | 8 ++++++++ etc/NEWS | 5 +++++ lisp/help-mode.el | 7 +++++-- lisp/help.el | 14 +++++++++++++- lisp/info-look.el | 44 ++++++++++++++++++++++++++------------------ 5 files changed, 57 insertions(+), 21 deletions(-) diff --git a/doc/emacs/help.texi b/doc/emacs/help.texi index 3c8f90da102..11ee9dc2b2f 100644 --- a/doc/emacs/help.texi +++ b/doc/emacs/help.texi @@ -34,6 +34,14 @@ is unconditionally selected by help commands, and if its value is @code{other}, the help window is selected only if there are more than two windows on the selected frame. +@vindex help-window-keep-selected + Conversely, many commands in the @samp{*Help*} buffer will pop up a +new window to display the results. For instance, clicking on the link +to show the source code, or using the @key{i} command to display the +manual entry, will (by default) pop up a new window. If +@code{help-window-keep-selected} is changed to non-@code{nil}, the +window displaying the @samp{*Help*} buffer will be reused instead. + @cindex searching documentation efficiently @cindex looking for a subject in documentation If you are looking for a certain feature, but don't know what it is diff --git a/etc/NEWS b/etc/NEWS index 882748d8c7f..5e7baab1096 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -443,6 +443,11 @@ command also works for non-Emoji characters.) ** Help ++++ +*** New user option 'help-window-keep-selected'. +If non-nil, commands to show the info manual and the source will reuse +the same window the *Help* buffer is shown in. + --- *** Commands like 'C-h f' have changed how they describe menu bindings. For instance, previously a command might be described as having the diff --git a/lisp/help-mode.el b/lisp/help-mode.el index cb87035281a..c725c0f1a15 100644 --- a/lisp/help-mode.el +++ b/lisp/help-mode.el @@ -268,7 +268,9 @@ The format is (FUNCTION ARGS...).") (let* ((location (find-function-search-for-symbol fun type file)) (position (cdr location))) - (pop-to-buffer (car location)) + (if help-window-keep-selected + (pop-to-buffer-same-window (car location)) + (pop-to-buffer (car location))) (run-hooks 'find-function-after-hook) (if position (progn @@ -819,7 +821,8 @@ The help buffers are divided into \"pages\" by the ^L character." (unless help-mode--current-data (error "No symbol to look up in the current buffer")) (info-lookup-symbol (plist-get help-mode--current-data :symbol) - 'emacs-lisp-mode)) + 'emacs-lisp-mode + help-window-keep-selected)) (defun help-goto-lispref-info () "View the Emacs Lisp manual *info* node of the current help item." diff --git a/lisp/help.el b/lisp/help.el index 2d08ceb86c7..fe999de6382 100644 --- a/lisp/help.el +++ b/lisp/help.el @@ -1802,13 +1802,25 @@ the help window appears on another frame, it may get selected and its frame get input focus even if this option is nil. This option has effect if and only if the help window was created -by `with-help-window'." +by `with-help-window'. + +Also see `help-window-keep-selected'." :type '(choice (const :tag "never (nil)" nil) (const :tag "other" other) (const :tag "always (t)" t)) :group 'help :version "23.1") +(defcustom help-window-keep-selected nil + "If non-nil, navigation commands in the *Help* buffer will reuse the window. +If nil, many commands in the *Help* buffer, like \\\\[help-view-source] and \\[help-goto-info], will +pop to a different window to display the results. + +Also see `help-window-select'." + :type 'boolean + :group 'help + :version "29.1") + (define-obsolete-variable-alias 'help-enable-auto-load 'help-enable-autoload "27.1") diff --git a/lisp/info-look.el b/lisp/info-look.el index aa07c3f5e70..6c8ef091a08 100644 --- a/lisp/info-look.el +++ b/lisp/info-look.el @@ -280,7 +280,7 @@ system." ;;;###autoload (put 'info-lookup-symbol 'info-file "emacs") ;;;###autoload -(defun info-lookup-symbol (symbol &optional mode) +(defun info-lookup-symbol (symbol &optional mode same-window) "Look up and display documentation of SYMBOL in the relevant Info manual. SYMBOL should be an identifier: a function or method, a macro, a variable, a data type, a class, etc. @@ -293,10 +293,13 @@ MODE is the major mode whose Info manuals to search for the documentation of SYMBOL. It defaults to the current buffer's `major-mode'; if that mode doesn't have any Info manuals known to Emacs, the command will prompt for MODE to use, with completion. With prefix arg, the command -always prompts for MODE." +always prompts for MODE. + +Is SAME-WINDOW, try to reuse the current window instead of +popping up a new one." (interactive (info-lookup-interactive-arguments 'symbol current-prefix-arg)) - (info-lookup 'symbol symbol mode)) + (info-lookup 'symbol symbol mode same-window)) ;;;###autoload (put 'info-lookup-file 'info-file "emacs") ;;;###autoload @@ -388,7 +391,7 @@ If optional argument QUERY is non-nil, query for the help mode." spec mode))) -(defun info-lookup (topic item mode) +(defun info-lookup (topic item mode &optional same-window) "Display the documentation of TOPIC whose name is ITEM, using MODE's manuals. TOPIC should be any known symbol of a help topic type, such as `file' or `symbol'. See the documentation of HELP-TOPIC in the doc @@ -397,7 +400,10 @@ ITEM is the item whose documentation to search: file name if TOPIC is `file', a symbol if TOPIC is `symbol', etc. MODE is the `major-mode' whose Info manuals to search for documentation of ITEM; if it's nil, the function uses `info-lookup-file-name-alist' -and the current buffer's file name to guess the mode.." +and the current buffer's file name to guess the mode. + +If SAME-WINDOW, reuse the current window. If nil, pop to a +different window." (or mode (setq mode (info-lookup-select-mode))) (setq mode (info-lookup--item-to-mode item mode)) (if-let ((info (info-lookup->mode-value topic mode))) @@ -423,19 +429,21 @@ and the current buffer's file name to guess the mode.." (if (not info-lookup-other-window-flag) (info) (save-window-excursion (info)) - (let* ((info-window (get-buffer-window "*info*" t)) - (info-frame (and info-window (window-frame info-window)))) - (if (and info-frame - (not (eq info-frame (selected-frame))) - (display-multi-frame-p) - (memq info-frame (frames-on-display-list))) - ;; *info* is visible in another frame on same display. - ;; Raise that frame and select the window. - (progn - (select-window info-window) - (raise-frame info-frame)) - ;; In any other case, switch to *info* in another window. - (switch-to-buffer-other-window "*info*"))))) + (if same-window + (pop-to-buffer-same-window "*info*") + (let* ((info-window (get-buffer-window "*info*" t)) + (info-frame (and info-window (window-frame info-window)))) + (if (and info-frame + (not (eq info-frame (selected-frame))) + (display-multi-frame-p) + (memq info-frame (frames-on-display-list))) + ;; *info* is visible in another frame on same display. + ;; Raise that frame and select the window. + (progn + (select-window info-window) + (raise-frame info-frame)) + ;; In any other case, switch to *info* another window. + (switch-to-buffer-other-window "*info*")))))) (while (and (not found) modes) (setq doc-spec (info-lookup->doc-spec topic (car modes))) (while (and (not found) doc-spec)