如何防止 Emacs 为编译输出打开新窗口?

11

当我调用编译命令时,如何防止Emacs打开新窗口?我想将其绑定到一个特定的现有窗口。

5个回答

9

根据您与卢克的评论,我建议您查看我使用的这个函数。我喜欢它,因为如果没有错误,它会隐藏编译缓冲区,否则它会保留它,以便您可以查看错误信息。

您可以在Emacs Wiki上查看页面,但是这里是代码:

;; Helper for compilation. Close the compilation window if
;; there was no error at all. (emacs wiki)
(defun compilation-exit-autoclose (status code msg)
  ;; If M-x compile exists with a 0
  (when (and (eq status 'exit) (zerop code))
    ;; then bury the *compilation* buffer, so that C-x b doesn't go there
    (bury-buffer)
    ;; and delete the *compilation* window
    (delete-window (get-buffer-window (get-buffer "*compilation*"))))
  ;; Always return the anticipated result of compilation-exit-message-function
  (cons msg code))
;; Specify my function (maybe I should have done a lambda function)
(setq compilation-exit-message-function 'compilation-exit-autoclose)

您可以随时切换回编译缓冲区查看任何警告。


嗯,谢谢,但是这种方法存在一个小问题。想象一下你有两个并排打开的窗口。你在左边的窗口中开始编译——它会在右边的窗口中打开。当编译结束后——你想要回到你的代码窗口,而这个脚本只会关闭它(也很烦人)。无论如何,我应该改进我的ELisp并且做正确的事情。 - Konstantine Rybnikov
@KonstantineRybnikov https://dev59.com/Z0fRa4cB1Zd3GeqP7DSA - CodyChan

3
您可以通过设置compilation-buffer-name-function函数来选择编译缓冲区的名称,该函数接受主模式的名称并返回缓冲区名称:
(setq compilation-buffer-name-function 
      '(lambda (maj-mode)
     "existing-buffer-name"))
然而,查看compliation-start的源代码,似乎在输出写入之前总是清除编译缓冲区(通过调用erase-buffer)。 编辑:如果我正确理解问题,您需要通过注释掉一行来修改compile.el文件中的compilation-start函数:
    ;; 弹出编译缓冲区。
    ;; http://lists.gnu.org/archive/html/emacs-devel/2007-11/msg01638.html
    ;; (setq outwin (display-buffer outbuf)) 

我对编译名称没问题。只是当编译不可见时,我不希望"compile"打开新窗口。 - Łukasz Lew
好的,所以你不想让*编译*缓冲区自动弹出?请看我的编辑答案。 - Luke Girvin
在默认的emacs lisp文件中注释东西并不好。你应该使用“defadvice”来代替。 - desudesudesu
1
(defadvice compilation-start (around inhidbit-display (command &optional mode name-function highlight-regexp)) (flet ((display-buffer)) (fset 'display-buffer 'ignore) ad-do-it)) (ad-activate 'compilation-start) (ad-deactivate 'compilation-start) 你也可以将你的函数设置在 'ignore 的位置,如果愿意的话。它将接受 display-buffer 参数。 - desudesudesu

2

不太确定你在问什么,但是如果你想要将缓冲区编译显示在当前窗口中,而不是显示在另一个窗口中,则:

(add-to-list 'same-window-buffer-names "*compilation*")

OP正在询问如何在另一个已存在的窗口中打开它,而不是在同一个窗口中打开。 - Chirag

1

结合 @zdav 的答案和 http://www.emacswiki.org/emacs/CompilationMode 中的代码,这是我为 compile 编写的全部代码,它提供了 4 个功能:

1). 使用 compile-again 自动运行上次相同的编译,无需提示。如果没有上一次记录或者有前置参数,它会像执行 M-x compile 一样。

2). compile 将分割当前窗口,不影响该窗口中的其他窗口。

3). 如果没有错误,它将自动关闭 *compilation* 缓冲区(窗口),否则保留。

4). 它将在 *compilation* 缓冲区中突出显示源代码的错误行和行号,使用 M-n/p 导航 *compilation* 缓冲区中的每个错误,在错误行中按 Enter 跳转到您的代码行。

(require 'compile)
(setq compilation-last-buffer nil)
(defun compile-again (ARG)
  "Run the same compile as the last time.

If there is no last time, or there is a prefix argument, this acts like M-x compile."
  (interactive "p")
  (if (and (eq ARG 1)
           compilation-last-buffer)
      (progn
        (set-buffer compilation-last-buffer)
        (revert-buffer t t))
    (progn
      (call-interactively 'compile)
      (setq cur (selected-window))
      (setq w (get-buffer-window "*compilation*"))
      (select-window w)
      (setq h (window-height w))
      (shrink-window (- h 10))
      (select-window cur))))
(global-set-key (kbd "C-x C-m") 'compile-again)
(defun my-compilation-hook ()
  "Make sure that the compile window is splitting vertically."
  (progn
    (if (not (get-buffer-window "*compilation*"))
        (progn
          (split-window-vertically)))))
(add-hook 'compilation-mode-hook 'my-compilation-hook)
(defun compilation-exit-autoclose (STATUS code msg)
  "Close the compilation window if there was no error at all."
  ;; If M-x compile exists with a 0
  (when (and (eq STATUS 'exit) (zerop code))
    ;; then bury the *compilation* buffer, so that C-x b doesn't go there
    (bury-buffer)
    ;; and delete the *compilation* window
    (delete-window (get-buffer-window (get-buffer "*compilation*"))))
  ;; Always return the anticipated result of compilation-exit-message-function
  (cons msg code))
(setq compilation-exit-message-function 'compilation-exit-autoclose)
(defvar all-overlays ())
(defun delete-this-overlay(overlay is-after begin end &optional len)
  (delete-overlay overlay)
  )
(defun highlight-current-line ()
"Highlight current line."
  (interactive)
  (setq current-point (point))
  (beginning-of-line)
  (setq beg (point))
  (forward-line 1)
  (setq end (point))
  ;; Create and place the overlay
  (setq error-line-overlay (make-overlay 1 1))

  ;; Append to list of all overlays
  (setq all-overlays (cons error-line-overlay all-overlays))

  (overlay-put error-line-overlay
               'face '(background-color . "red"))
  (overlay-put error-line-overlay
               'modification-hooks (list 'delete-this-overlay))
  (move-overlay error-line-overlay beg end)
  (goto-char current-point))
(defun delete-all-overlays ()
  "Delete all overlays"
  (while all-overlays
    (delete-overlay (car all-overlays))
    (setq all-overlays (cdr all-overlays))))
(defun highlight-error-lines(compilation-buffer process-result)
  (interactive)
  (delete-all-overlays)
  (condition-case nil
      (while t
        (next-error)
        (highlight-current-line))
    (error nil)))
(setq compilation-finish-functions 'highlight-error-lines)

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接