2

Emacs behaviour which recently[*] started to irritate me:

  • I edit the file, and need some help
  • M-x man something
  • emacs politely splits frame into two windows and opens manpage there, I see both source and man, great
  • while reading man I find that I need to followup further, so I M-x man anothertopic
  • emacs opens new manpage in window previously occupied by my source, I see two manpages on the screen and can't edit anymore (until I switch buffer)

Is it possible to make Man prefer reuse existing man window?

Mekk
  • 1,441
  • 10
  • 12
  • How about setting your first window as dedicated? http://www.gnu.org/software/emacs/manual/html_node/elisp/Dedicated-Windows.html – lawlist Feb 03 '15 at 22:08
  • You may also wish to modify the function `Man-notify-when-ready` as the variable `Man-notify-method` does not appear to offer the precise behavior you seek. Perhaps there is an acceptable alternative behavior you can choose based on the options mentioned in the document string for the variable `Man-notify-method`. – lawlist Feb 03 '15 at 23:07

1 Answers1

3

Adapting display-buffer-reuse-window to create display-buffer-reuse-major-mode-window, we can then use display-buffer-alist to specify that this be used to display buffers in Man-mode.

Obviously the first form can also be trivially modified to apply to any number of modes besides Man-mode.

(add-to-list 'display-buffer-alist
             (cons (lambda (buffer alist)
                     (with-current-buffer buffer
                       (eq major-mode 'Man-mode)))
                   (cons 'display-buffer-reuse-major-mode-window
                         '((inhibit-same-window . nil)
                           (reusable-frames . visible)
                           (inhibit-switch-frame . nil)))))

(defun display-buffer-reuse-major-mode-window (buffer alist)
  "Return a window displaying a buffer in BUFFER's major mode.
Return nil if no usable window is found.

If ALIST has a non-nil `inhibit-same-window' entry, the selected
window is not eligible for reuse.

If ALIST contains a `reusable-frames' entry, its value determines
which frames to search for a reusable window:
  nil -- the selected frame (actually the last non-minibuffer frame)
  A frame   -- just that frame
  `visible' -- all visible frames
  0   -- all frames on the current terminal
  t   -- all frames.

If ALIST contains no `reusable-frames' entry, search just the
selected frame if `display-buffer-reuse-frames' and
`pop-up-frames' are both nil; search all frames on the current
terminal if either of those variables is non-nil.

If ALIST has a non-nil `inhibit-switch-frame' entry, then in the
event that a window on another frame is chosen, avoid raising
that frame."
  (let* ((alist-entry (assq 'reusable-frames alist))
         (frames (cond (alist-entry (cdr alist-entry))
                       ((if (eq pop-up-frames 'graphic-only)
                            (display-graphic-p)
                          pop-up-frames)
                        0)
                       (display-buffer-reuse-frames 0)
                       (t (last-nonminibuffer-frame))))
         (window (let ((mode (with-current-buffer buffer major-mode)))
                   (if (and (eq mode (with-current-buffer (window-buffer)
                                       major-mode))
                            (not (cdr (assq 'inhibit-same-window alist))))
                       (selected-window)
                     (catch 'window
                       (walk-windows
                        (lambda (w)
                          (and (window-live-p w)
                               (eq mode (with-current-buffer (window-buffer w)
                                          major-mode))
                               (not (eq w (selected-window)))
                               (throw 'window w)))
                        'nomini frames))))))
    (when (window-live-p window)
      (prog1 (window--display-buffer buffer window 'reuse alist)
        (unless (cdr (assq 'inhibit-switch-frame alist))
          (window--maybe-raise-frame (window-frame window)))))))
phils
  • 71,335
  • 11
  • 153
  • 198
  • Great! Thank you, works just as I wanted. PS Considering amount of code, mayhaps it deserves being polished slightly (I am just to try writing function enable-reuse-for which would wrap first snippet) and published as package? – Mekk Feb 06 '15 at 12:28
  • I might submit `display-buffer-reuse-major-mode-window` as an enhancement. It seems like a reasonable feature. – phils Feb 06 '15 at 12:33
  • Here is my take on adding the aforementioned function: https://gist.github.com/Mekk/aad77cf3401a17e5df0d (complete file including your code) – Mekk Feb 06 '15 at 13:24
  • And one thing it would be nice to merge with your solution is an option to handle also mode groups (cases where a few modes share the same window, my main case is various compilation derivatives). Some take is here http://emacs.stackexchange.com/questions/8007/sharing-compilation-window-with-other-compilation-like-commands/8012 – Mekk Feb 06 '15 at 19:01
  • 2
    Update: `display-buffer-reuse-mode-window` is now in emacs (certainly in v26.1). – Fran Burstall Feb 01 '19 at 19:29