1

I looking for simple solution to open clickable filenames in the same help buffers. For example, when we display help for add-to-list variable and click TAB the cursor is placed on the subr.el file link. We can click the link to open this file in other window. I look for solution that will open the file in the same window rather rather than other one.

I was looking for a solution to this problem and found Make opening clickable filenames from Help mode in same window, but this is too over complicated in my opinion to use (it involves using timers and killing other buffers), even if the author claim it's working.

I wonder if after 4 years of initial questions anyone can propose any better solution to this problem.

3
  • Please clarify what you want. Maybe specify what isn't sufficient in the linked solution. "Too weird" doesn't clarify what you're requesting.
    – Drew
    Commented Feb 4, 2021 at 20:10
  • @Drew thanks for your interest, I edited the post.
    – Navidot
    Commented Feb 4, 2021 at 21:16
  • Now after 1 year of the question, I still don't see an answer which isn't adding a lot of code in the configs.
    – scribe
    Commented May 26, 2022 at 0:41

2 Answers 2

2

You can use the function windmove-display-same-window from windmove.el for this.

(global-set-key (kbd "M-S-0") #'windmove-display-same-window)

Then, in the help buffer, you can type M-S-0 and click the link with mouse-2 (i.e. middle click if you have the button, otherwise it's click with the left and right buttons simultaneously) to visit the linked file in the same window. It works with any command that displays a new buffer, so you can also use M-S-0 before hitting RET on the link, or type M-S-0 C-h f RET add-to-list RET to replace the buffer you're in with the help buffer, and so on.

There are other functions in windmove.el that tell Emacs to in what direction to place the window to be created, and more. Have a look a the various windmove-display-* function and at the code of windmove.el for more information.

2

The following answer will affect clicking on the filename link in the *Help* buffer after calling either C-h v aka M-x describe-variable or C-h f aka M-x describe-function. The answer has been tested using Emacs 27, without any user-configuration other than the code snippet hereinbelow. It may also be possible to add an entry to the display-buffer-alist with a custom function to achieve the desired behavior, but I chose to modify the code directly instead.

A comment by the O.P. in the linked thread, which was cited by the O.P. of the current thread, states (underneath the accepted answer) as follows: "just a quick note - I made it work just changing in help-function-def and help-variable-def function calls of pop-to-buffer to switch-to-buffer ...." By examining the code at issue, I chose to use set-window-buffer. So that anyone who uses this answer in the future can see that this works, I have included some messages at the outset of the functions ... feel free to comment them out after testing it "as-is" to verify it works as advertised. Don't forget to copy the last two (2) closing parentheses at the tail end of the code snippet ... I separated them so that we can visualize that they close out the with-eval-after-load and progn statements ...

(with-eval-after-load 'help-mode
  (progn

    (defun my-help-function-def--button-function (fun &optional file type)
      (message "my-help-function-def--button-function:  %s %s %s" fun file type)
      (or file
          (setq file (find-lisp-object-file-name fun type)))
      (if (not file)
          (message "Unable to find defining file")
        (require 'find-func)
        (when (eq file 'C-source)
          (setq file
                (help-C-file-name (indirect-function fun) 'fun)))
        ;; Don't use find-function-noselect because it follows
        ;; aliases (which fails for built-in functions).
        (let* ((location (find-function-search-for-symbol fun type file))
               (position (cdr location)))
          ;;; The original behavior is to call `pop-to-buffer' commented out hereinbelow:
          ;;;   (pop-to-buffer (car location))
          ;;;
          ;;; The O.P. of the following thread wishes to display the function
          ;;; definition in the same window as the *Help* buffer:
          ;;; https://emacs.stackexchange.com/q/63176/2287
          (set-window-buffer (selected-window) (car location))
          (run-hooks 'find-function-after-hook)
          (if position
              (progn
                ;; Widen the buffer if necessary to go to this position.
                (when (or (< position (point-min))
                          (> position (point-max)))
                  (widen))
                (goto-char position))
            (message "Unable to find location in file")))))

    ;;; In Emacs 27, the default behavior is to call `help-function-def--button-function'.
    ;;; The O.P. of the following thread wishes to display the function definition in
    ;;; the same window as the *Help* buffer:  https://emacs.stackexchange.com/q/63176/2287
    (define-button-type 'help-function-def
      :supertype 'help-xref
      'help-function #'my-help-function-def--button-function
      'help-echo (purecopy "mouse-2, RET: find function's definition"))

    (define-button-type 'help-variable-def
      :supertype 'help-xref
      'help-function (lambda (var &optional file)
           (message "help-variable-def / help-function:  %s %s" var file)
           (when (eq file 'C-source)
             (setq file (help-C-file-name var 'var)))
           (let* ((location (find-variable-noselect var file))
                  (position (cdr location)))
             ;;; The original behavior is to call `pop-to-buffer' commented out hereinbelow:
             ;;;   (pop-to-buffer (car location))
             ;;;
             ;;; The O.P. of the following thread wishes to display the variable
             ;;; definition in the same window as the *Help* buffer:
             ;;; https://emacs.stackexchange.com/q/63176/2287
             (set-window-buffer (selected-window) (car location))
             (run-hooks 'find-function-after-hook)
                         (if position
                               (progn
                                 ;; Widen the buffer if necessary to go to this position.
                                 (when (or (< position (point-min))
                                           (> position (point-max)))
                                   (widen))
                                 (goto-char position))
                           (message "Unable to find location in file"))))
      'help-echo (purecopy "mouse-2, RET: find variable's definition"))

  ))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.