When building, a split view is opened for the output.

It's possible to close this window, open a new window and set the buffer to the build output.

However when building again, the other window isn't used. Instead a new split is created in the same window the source code is in.

Is there some way to use any existing compiler output windows instead of creating new splits?

  • Cannot reproduce. Do you have popwin-mode on? If so, try turning it off with (popwin-mode -1). – Tianxiang Xiong Mar 29 '17 at 5:30
  • I don't have popwin* variable or mode available (latest emacs). – ideasman42 Mar 29 '17 at 5:42

Does this do what you want?

It provides a display-buffer-reuse-major-mode-window function for use with display-buffer-alist, and configures an entry which targets compilation-mode buffers.

You can then adapt the display-buffer-alist entry to target additional modes if you want this behaviour for other kinds of buffer as well.

;; Always open compilation buffers in the same window.
(add-to-list 'display-buffer-alist
             (cons (lambda (buffer alist)
                     (with-current-buffer buffer
                       (eq major-mode 'compilation-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-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)
                            (not (cdr (assq 'inhibit-same-window alist))))
                     (catch 'window
                        (lambda (w)
                          (and (window-live-p w)
                               (eq mode (with-current-buffer (window-buffer w)
                               (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)))))))
  • That said, I concur with Tianxiang Xiong in that I cannot reproduce the problem -- the default behaviour in 25.3 appears to be exactly what you've asked for. – phils Nov 22 '17 at 5:57
(defun switch-to-frame ()
  (setq frame-name "compile")
  (let ((frames (frame-list)))
    (catch 'break
      (while frames
        (let ((frame (car frames)))
      (if (equal (frame-parameter frame 'name) frame-name)
          (throw 'break (select-frame-set-input-focus frame))
        (make-frame '((name . "compile") (width . 120) (height . 20) (fullscreen . nil)))
        (select-frame-by-name frame-name)
        (setq frames (cdr frames))
(defun my-compile ()
  (call-interactively 'compile))

Hi i'm still learning elisp at the moment and i'm not very good at it but this are two functions taken somewhere from the internet and are slightly modified.The first one checks if there is a frame called "compile" if so it jumps to it if not than it calls make-frame and jumps to it. The second function calls the interactive Lisp function compile in that frame.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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